mirror of
https://github.com/IvarK/AntimatterDimensionsSourceCode.git
synced 2024-11-22 04:05:42 +00:00
Restructure Steam and Electron code
This commit is contained in:
parent
7ec351dd2b
commit
c33e34d50d
@ -1,4 +1,4 @@
|
|||||||
public/**/*.js
|
public/**/*.js
|
||||||
src/components/SliderComponent.vue
|
src/components/SliderComponent.vue
|
||||||
javascripts/supported-browsers.js
|
javascripts/supported-browsers.js
|
||||||
src/steam/PlayFabClientApi.js
|
src/steam/bindings/PlayFabClientApi.js
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { SteamRuntime } from "@/steam";
|
||||||
import { GameMechanicState } from "../game-mechanics/index";
|
import { GameMechanicState } from "../game-mechanics/index";
|
||||||
|
|
||||||
class AchievementState extends GameMechanicState {
|
class AchievementState extends GameMechanicState {
|
||||||
@ -70,7 +71,7 @@ class AchievementState extends GameMechanicState {
|
|||||||
GameUI.notify.reality(`Automatically unlocked: ${this.name}`);
|
GameUI.notify.reality(`Automatically unlocked: ${this.name}`);
|
||||||
} else {
|
} else {
|
||||||
GameUI.notify.success(`Achievement: ${this.name}`);
|
GameUI.notify.success(`Achievement: ${this.name}`);
|
||||||
SteamFunctions.GiveAchievement(this.id);
|
SteamRuntime.activateAchievement(this.id);
|
||||||
}
|
}
|
||||||
if (player.speedrun.isActive && !player.speedrun.achievementTimes[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
|
// 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() {
|
get power() {
|
||||||
if (Pelle.isDisabled("achievementMult")) return 1;
|
if (Pelle.isDisabled("achievementMult")) return 1;
|
||||||
return Achievements._power.value;
|
return Achievements._power.value;
|
||||||
|
},
|
||||||
|
|
||||||
|
updateSteamStatus() {
|
||||||
|
for (const achievement in Achievements.all.filter(x => x.isUnlocked)) {
|
||||||
|
SteamRuntime.activateAchievement(achievement.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { ElectronRuntime } from "@/steam";
|
||||||
import { sha512_256 } from "js-sha512";
|
import { sha512_256 } from "js-sha512";
|
||||||
|
|
||||||
import { DEV } from "@/env";
|
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
|
// 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
|
// So the classes on body need to be updated
|
||||||
Themes.find(Theme.currentName()).set();
|
Themes.find(Theme.currentName()).set();
|
||||||
SteamFunctions.UIZoom()
|
ElectronRuntime.updateZoom();
|
||||||
GameStorage.save();
|
GameStorage.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,3 +46,7 @@ window.onerror = (event, source) => {
|
|||||||
if (!source.endsWith(".js")) return;
|
if (!source.endsWith(".js")) return;
|
||||||
GlobalErrorHandler.onerror(event);
|
GlobalErrorHandler.onerror(event);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
window.addEventListener("unhandledrejection", event => {
|
||||||
|
GlobalErrorHandler.onerror(event);
|
||||||
|
});
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
|
import { discordRichPresence } from "./secret-formula/discord-rich-presence";
|
||||||
|
|
||||||
export const RichPresenceInfo = {
|
export const RichPresenceInfo = {
|
||||||
get gameStage() {
|
get gameStage() {
|
||||||
const stageDB = GameDatabase.discordRichPresence.stages;
|
const stageDB = discordRichPresence.stages;
|
||||||
for (let stage = stageDB.length - 1; stage >= 0; stage--) {
|
for (let stage = stageDB.length - 1; stage >= 0; stage--) {
|
||||||
if (stageDB[stage].hasReached()) return stageDB[stage];
|
if (stageDB[stage].hasReached()) return stageDB[stage];
|
||||||
}
|
}
|
||||||
throw Error("No valid progress stage found");
|
throw Error("No valid progress stage found");
|
||||||
},
|
},
|
||||||
get challengeState() {
|
get challengeState() {
|
||||||
const challDB = GameDatabase.discordRichPresence.challenges;
|
const challDB = discordRichPresence.challenges;
|
||||||
for (let index = 0; index < challDB.length; index++) {
|
for (let index = 0; index < challDB.length; index++) {
|
||||||
const chall = challDB[index];
|
const chall = challDB[index];
|
||||||
if (chall.activityToken()) return chall;
|
if (chall.activityToken()) return chall;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { ElectronRuntime } from "@/steam";
|
||||||
import Mousetrap from "mousetrap";
|
import Mousetrap from "mousetrap";
|
||||||
|
|
||||||
import { GameKeyboard } from "./keyboard";
|
import { GameKeyboard } from "./keyboard";
|
||||||
@ -280,28 +281,28 @@ export const shortcuts = [
|
|||||||
name: "Zoom In",
|
name: "Zoom In",
|
||||||
keys: ["ctrl", "="],
|
keys: ["ctrl", "="],
|
||||||
type: "bind",
|
type: "bind",
|
||||||
function: () => {SteamFunctions.SetZoomLevel("Increase")},
|
function: () => ElectronRuntime.increaseZoom(),
|
||||||
visible: () => false
|
visible: () => false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Zoom In",
|
name: "Zoom In",
|
||||||
keys: ["ctrl", "+"],
|
keys: ["ctrl", "+"],
|
||||||
type: "bind",
|
type: "bind",
|
||||||
function: () => {SteamFunctions.SetZoomLevel("Increase")},
|
function: () => ElectronRuntime.increaseZoom(),
|
||||||
visible: () => false
|
visible: () => false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Zoom Out",
|
name: "Zoom Out",
|
||||||
keys: ["ctrl", "-"],
|
keys: ["ctrl", "-"],
|
||||||
type: "bind",
|
type: "bind",
|
||||||
function: () => {SteamFunctions.SetZoomLevel("Decrease")},
|
function: () => ElectronRuntime.decreaseZoom(),
|
||||||
visible: () => false
|
visible: () => false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Reset Zoom",
|
name: "Reset Zoom",
|
||||||
keys: ["ctrl", "0"],
|
keys: ["ctrl", "0"],
|
||||||
type: "bind",
|
type: "bind",
|
||||||
function: () => {SteamFunctions.ResetZoom()},
|
function: () => ElectronRuntime.resetZoom(),
|
||||||
visible: () => false
|
visible: () => false
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -90,7 +90,7 @@ const Payments = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// Sends a request to purchase a STD upgrade, returning true if successful (and syncs data), false if not
|
// 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;
|
if (!Cloud.loggedIn) return false;
|
||||||
let res;
|
let res;
|
||||||
try {
|
try {
|
||||||
@ -103,7 +103,7 @@ const Payments = {
|
|||||||
user: Cloud.user.id,
|
user: Cloud.user.id,
|
||||||
upgrade: upgradeKey,
|
upgrade: upgradeKey,
|
||||||
extraData: {
|
extraData: {
|
||||||
requestedSet: GlyphAppearanceHandler.chosenFromModal?.id,
|
requestedSet: cosmeticName,
|
||||||
fullCompletions: player.records.fullGameCompletions
|
fullCompletions: player.records.fullGameCompletions
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
|
// 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
|
// 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
|
* 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
|
* 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;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { SteamRuntime } from "@/steam";
|
||||||
import { RebuyableMechanicState } from "./game-mechanics/index";
|
import { RebuyableMechanicState } from "./game-mechanics/index";
|
||||||
|
|
||||||
import Payments from "./payments";
|
import Payments from "./payments";
|
||||||
@ -177,8 +178,14 @@ class ShopPurchaseState extends RebuyableMechanicState {
|
|||||||
if (GameEnd.creditsEverClosed) return false;
|
if (GameEnd.creditsEverClosed) return false;
|
||||||
if (this.config.instantPurchase && ui.$viewModel.modal.progressBar) return false;
|
if (this.config.instantPurchase && ui.$viewModel.modal.progressBar) return false;
|
||||||
|
|
||||||
// Contact the firebase server to verify the purchase
|
const cosmeticName = this.config.key === "singleCosmeticSet"
|
||||||
const success = true//await Payments.buyUpgrade(this.config.key);
|
? 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 (!success) return false;
|
||||||
|
|
||||||
if (player.IAP.enabled) Speedrun.setSTDUse(true);
|
if (player.IAP.enabled) Speedrun.setSTDUse(true);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* eslint-disable import/extensions */
|
/* eslint-disable import/extensions */
|
||||||
|
import { SteamRuntime } from "@/steam";
|
||||||
import pako from "pako/dist/pako.esm.mjs";
|
import pako from "pako/dist/pako.esm.mjs";
|
||||||
/* eslint-enable import/extensions */
|
/* 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) {
|
async manualCloudLogin(EmailAddress,Password) {
|
||||||
//try{
|
//try{
|
||||||
@ -234,16 +258,15 @@ export const Cloud = {
|
|||||||
if (user) {
|
if (user) {
|
||||||
this.user = {
|
this.user = {
|
||||||
id: user.uid,
|
id: user.uid,
|
||||||
displayName: steamOn ? Steam.getSteamId().screenName : "",//user.displayName,
|
displayName: SteamRuntime.isActive
|
||||||
|
? SteamRuntime.screenName
|
||||||
|
: user.displayName,
|
||||||
email: user.email,
|
email: user.email,
|
||||||
};
|
};
|
||||||
SteamFunctions.SyncPlayFabSTD()
|
SteamRuntime.syncIap();
|
||||||
} else {
|
} else {
|
||||||
this.user = null;
|
this.user = null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
Cloud.init();
|
|
||||||
//this.user.displayName = Steam.getSteamId().screenName
|
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
|
import { SteamRuntime } from "@/steam";
|
||||||
import * as ADNotations from "@antimatter-dimensions/notations";
|
import * as ADNotations from "@antimatter-dimensions/notations";
|
||||||
|
|
||||||
import { DEV } from "@/env";
|
import { DEV } from "@/env";
|
||||||
|
|
||||||
import { deepmergeAll } from "@/utility/deepmerge";
|
import { deepmergeAll } from "@/utility/deepmerge";
|
||||||
|
import { Achievement } from "../achievements/normal-achievement";
|
||||||
|
|
||||||
export const GameStorage = {
|
export const GameStorage = {
|
||||||
currentSlot: 0,
|
currentSlot: 0,
|
||||||
@ -30,7 +32,7 @@ export const GameStorage = {
|
|||||||
const root = GameSaveSerializer.deserialize(save);
|
const root = GameSaveSerializer.deserialize(save);
|
||||||
|
|
||||||
this.loadRoot(root);
|
this.loadRoot(root);
|
||||||
SteamFunctions.BackfillAchievements()
|
Achievements.updateSteamStatus();
|
||||||
},
|
},
|
||||||
|
|
||||||
loadRoot(root) {
|
loadRoot(root) {
|
||||||
@ -66,7 +68,7 @@ export const GameStorage = {
|
|||||||
Tabs.all.find(t => t.id === player.options.lastOpenTab).show(true);
|
Tabs.all.find(t => t.id === player.options.lastOpenTab).show(true);
|
||||||
Cloud.resetTempState();
|
Cloud.resetTempState();
|
||||||
GameUI.notify.info("Game loaded");
|
GameUI.notify.info("Game loaded");
|
||||||
SteamFunctions.BackfillAchievements()
|
Achievements.updateSteamStatus();
|
||||||
},
|
},
|
||||||
|
|
||||||
import(saveData) {
|
import(saveData) {
|
||||||
@ -93,7 +95,7 @@ export const GameStorage = {
|
|||||||
// is showing
|
// is showing
|
||||||
Tab.options.subtabs[0].show();
|
Tab.options.subtabs[0].show();
|
||||||
GameUI.notify.info("Game imported");
|
GameUI.notify.info("Game imported");
|
||||||
SteamFunctions.BackfillAchievements()
|
Achievements.updateSteamStatus();
|
||||||
},
|
},
|
||||||
|
|
||||||
importAsFile() {
|
importAsFile() {
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
|
import { ElectronRuntime, SteamRuntime } from "@/steam";
|
||||||
import TWEEN from "tween.js";
|
import TWEEN from "tween.js";
|
||||||
|
|
||||||
import { DC } from "./core/constants";
|
import { DC } from "./core/constants";
|
||||||
import { deepmergeAll } from "@/utility/deepmerge";
|
import { deepmergeAll } from "@/utility/deepmerge";
|
||||||
import { playFabLogin } from "./core/playfab";
|
|
||||||
import { DEV } from "@/env";
|
import { DEV } from "@/env";
|
||||||
import { SpeedrunMilestones } from "./core/speedrun";
|
import { SpeedrunMilestones } from "./core/speedrun";
|
||||||
|
import { Cloud } from "./core/storage";
|
||||||
import { supportedBrowsers } from "./supported-browsers";
|
import { supportedBrowsers } from "./supported-browsers";
|
||||||
|
|
||||||
import Payments from "./core/payments";
|
import Payments from "./core/payments";
|
||||||
@ -1022,12 +1023,6 @@ window.onload = function() {
|
|||||||
GameUI.initialized = supportedBrowser;
|
GameUI.initialized = supportedBrowser;
|
||||||
ui.view.initialized = supportedBrowser;
|
ui.view.initialized = supportedBrowser;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if(Steam){
|
|
||||||
if(Steam.initAPI()){
|
|
||||||
playFabLogin();
|
|
||||||
if(SteamFunctions.discordOn){SteamFunctions.SetRichPresence()};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
document.getElementById("loading").style.display = "none";
|
document.getElementById("loading").style.display = "none";
|
||||||
}, 500);
|
}, 500);
|
||||||
if (!supportedBrowser) {
|
if (!supportedBrowser) {
|
||||||
@ -1064,15 +1059,11 @@ export function init() {
|
|||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log("👨💻 Development Mode 👩💻");
|
console.log("👨💻 Development Mode 👩💻");
|
||||||
}
|
}
|
||||||
|
ElectronRuntime.initialize();
|
||||||
|
SteamRuntime.initialize();
|
||||||
|
Cloud.init();
|
||||||
GameStorage.load();
|
GameStorage.load();
|
||||||
Tabs.all.find(t => t.config.id === player.options.lastOpenTab).show(true);
|
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();
|
Payments.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
@ -44,37 +44,6 @@
|
|||||||
</video>
|
</video>
|
||||||
</div>
|
</div>
|
||||||
<div id="performance-stats" class="c-performance-stats" style="display: none;"></div>
|
<div id="performance-stats" class="c-performance-stats" style="display: none;"></div>
|
||||||
|
|
||||||
<script type="text/javascript" src="Steam/steam.js"></script>
|
|
||||||
<canvas id="forceRefreshCanvas" style="position: fixed; right: 0px; bottom: 0px; width: 100vw; height: 100%; opacity: 0.01; pointer-events: none; z-index: -20;"></canvas>
|
|
||||||
<script>
|
|
||||||
/*--Post GameLoad Steam Initialization--*/
|
|
||||||
var nodeOn = window.require!==undefined ? true : false
|
|
||||||
steamOn=false
|
|
||||||
if(nodeOn){
|
|
||||||
var JQ = require('jquery');
|
|
||||||
var Steam = require('greenworks')
|
|
||||||
var shell = require('electron').shell;
|
|
||||||
if (Steam) {
|
|
||||||
if (Steam.initAPI()) {
|
|
||||||
console.log("Steam is Functional!")
|
|
||||||
steamOn = true
|
|
||||||
} else {
|
|
||||||
console.log("Steam API not activated. Are you sure you opened the game in Steam?")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
JQ(window).resize(function(){
|
|
||||||
SteamFunctions.UIZoom()
|
|
||||||
});
|
|
||||||
if(Steam){
|
|
||||||
if(Steam.initAPI()){
|
|
||||||
SteamFunctions.SteamInitialize()
|
|
||||||
}else{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//console.log("SteamOn is "+steamOn)
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
<script>
|
<script>
|
||||||
// We use an IE only document variable to check here to force it to show the browser warning.
|
// We use an IE only document variable to check here to force it to show the browser warning.
|
||||||
|
@ -31,6 +31,17 @@ html {
|
|||||||
background: white;
|
background: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
._steam-refresh-canvas {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: fixed;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: -20;
|
||||||
|
opacity: 0.01;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
<script>
|
<script>
|
||||||
|
import { openExternalLink } from "@/utility/open-external-link";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "InformationModalButton",
|
name: "InformationModalButton",
|
||||||
props: {
|
props: {
|
||||||
@ -25,9 +27,7 @@ export default {
|
|||||||
openAssociatedModal() {
|
openAssociatedModal() {
|
||||||
Modal[this.showModal].show();
|
Modal[this.showModal].show();
|
||||||
},
|
},
|
||||||
openExternalLink(){
|
openExternalLink
|
||||||
shell.openExternal(this.link);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import ModalWrapper from "@/components/modals/ModalWrapper";
|
import ModalWrapper from "@/components/modals/ModalWrapper";
|
||||||
import StdStoreRow from "@/components/modals/StdStoreRow";
|
import StdStoreRow from "@/components/modals/StdStoreRow";
|
||||||
|
import { SteamRuntime } from "@/steam";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "StdStoreModal",
|
name: "StdStoreModal",
|
||||||
@ -15,10 +16,10 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
update() {
|
update() {
|
||||||
this.macPurchaser = SteamFunctions.macUser && SteamFunctions.purchaseChecker.length > 0;
|
this.macPurchaser = SteamRuntime.hasPendingPurchaseConfirmations;
|
||||||
},
|
},
|
||||||
macConfirm() {
|
macConfirm() {
|
||||||
SteamFunctions.PurchaseValidation();
|
SteamRuntime.validatePurchases();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -29,8 +30,8 @@ export default {
|
|||||||
<template #header>
|
<template #header>
|
||||||
Support The Developer - coins
|
Support The Developer - coins
|
||||||
</template>
|
</template>
|
||||||
<span id='MacConfirm' v-if="macPurchaser">
|
<span v-if="macPurchaser">
|
||||||
<button class='o-shop-button-button' @click="macConfirm()">Confirm Purchase to Receive STDs</button>
|
<button class="o-shop-button-button" @click="macConfirm()">Confirm Purchase to Receive STDs</button>
|
||||||
<br><span>(Required on Mac)</span><br>
|
<br><span>(Required on Mac)</span><br>
|
||||||
</span>
|
</span>
|
||||||
<div class="l-modal-store-content">
|
<div class="l-modal-store-content">
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<script>
|
<script>
|
||||||
|
import { SteamRuntime } from "@/steam";
|
||||||
import Payments from "../../../javascripts/core/payments";
|
import Payments from "../../../javascripts/core/payments";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -15,7 +16,7 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
purchase() {
|
purchase() {
|
||||||
SteamFunctions.PurchaseIAP(this.amount, this.cost);
|
SteamRuntime.purchaseIap(this.amount);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<script>
|
<script>
|
||||||
|
import { ElectronRuntime } from "@/steam";
|
||||||
import SliderComponent from "@/components/SliderComponent";
|
import SliderComponent from "@/components/SliderComponent";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -8,7 +9,7 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
updatedZoom: 0
|
zoomLevel: 0
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -24,14 +25,11 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
update() {
|
update() {
|
||||||
this.updatedZoom = Math.round(SteamFunctions.zoomLevel*100);
|
this.zoomLevel = Math.round(ElectronRuntime.zoomFactor * 100);
|
||||||
},
|
},
|
||||||
adjustSliderValue(value) {
|
adjustSliderValue(value) {
|
||||||
this.updatedZoom = value;
|
this.zoomLevel = value;
|
||||||
SteamFunctions.zoomLevel = Math.round(value/10)/10
|
ElectronRuntime.zoomLevel = Math.round(value / 10) / 10;
|
||||||
localStorage.setItem("Zoom",SteamFunctions.zoomLevel)
|
|
||||||
SteamFunctions.UIZoom()
|
|
||||||
GameUI.notify.info(`Size changed to ${Math.round(SteamFunctions.zoomLevel*100)}%`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -39,11 +37,11 @@ export default {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="o-primary-btn o-primary-btn--option o-primary-btn--slider l-options-grid__button">
|
<div class="o-primary-btn o-primary-btn--option o-primary-btn--slider l-options-grid__button">
|
||||||
<b>Zoom Level: {{ formatInt(updatedZoom) }}%</b>
|
<b>Zoom Level: {{ formatInt(zoomLevel) }}%</b>
|
||||||
<SliderComponent
|
<SliderComponent
|
||||||
class="o-primary-btn--slider__slider"
|
class="o-primary-btn--slider__slider"
|
||||||
v-bind="sliderProps"
|
v-bind="sliderProps"
|
||||||
:value="updatedZoom"
|
:value="zoomLevel"
|
||||||
@input="adjustSliderValue($event)"
|
@input="adjustSliderValue($event)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
<script>
|
<script>
|
||||||
import { purchase } from 'vue-gtag';
|
|
||||||
export default {
|
export default {
|
||||||
name: "ShopButton",
|
name: "ShopButton",
|
||||||
props: {
|
props: {
|
||||||
@ -45,10 +44,11 @@ export default {
|
|||||||
openSelectionModal() {
|
openSelectionModal() {
|
||||||
Modal.cosmeticSetChoice.show();
|
Modal.cosmeticSetChoice.show();
|
||||||
},
|
},
|
||||||
SteamPurchase(){
|
performPurchase() {
|
||||||
if(!this.isSingleCosmeticSet || this.hasChosen){
|
if (this.isSingleCosmeticSet && !this.hasChosen) {
|
||||||
SteamFunctions.PurchaseShopItem(this.purchase.cost,this.purchase.config.key,this.purchase.config,this.chosenSet)
|
return;
|
||||||
}
|
}
|
||||||
|
this.purchase.purchase();
|
||||||
},
|
},
|
||||||
purchaseButtonObject() {
|
purchaseButtonObject() {
|
||||||
return {
|
return {
|
||||||
@ -105,7 +105,7 @@ export default {
|
|||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
:class="purchaseButtonObject()"
|
:class="purchaseButtonObject()"
|
||||||
@click="SteamPurchase()"
|
@click="performPurchase"
|
||||||
>
|
>
|
||||||
Cost: {{ cost }}
|
Cost: {{ cost }}
|
||||||
<img
|
<img
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<script>
|
<script>
|
||||||
import "vue-loading-overlay/dist/vue-loading.css";
|
import "vue-loading-overlay/dist/vue-loading.css";
|
||||||
|
import { STEAM } from "@/env";
|
||||||
|
|
||||||
import Loading from "vue-loading-overlay";
|
import Loading from "vue-loading-overlay";
|
||||||
|
|
||||||
@ -33,7 +34,7 @@ export default {
|
|||||||
return ShopPurchase.all;
|
return ShopPurchase.all;
|
||||||
},
|
},
|
||||||
buySTDText() {
|
buySTDText() {
|
||||||
return steamOn ? "Buy More" : "Play Online on Steam to buy STDs";
|
return STEAM ? "Buy More" : "Play Online on Steam to buy STDs";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@ -67,7 +68,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
showStore() {
|
showStore() {
|
||||||
if (!steamOn) return;
|
if (!STEAM) return;
|
||||||
if (this.creditsClosed) return;
|
if (this.creditsClosed) return;
|
||||||
SecretAchievement(33).unlock();
|
SecretAchievement(33).unlock();
|
||||||
if (this.loggedIn) Modal.shop.show();
|
if (this.loggedIn) Modal.shop.show();
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
|
import { openExternalLink } from "@/utility/open-external-link";
|
||||||
|
import { STEAM } from "@/env";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "NewsTicker",
|
name: "NewsTicker",
|
||||||
data() {
|
data() {
|
||||||
@ -72,7 +75,14 @@ export default {
|
|||||||
this.currentNews.reset();
|
this.currentNews.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
line.innerHTML = this.currentNews.text.replace(/href='/g, `onClick='shell.openExternal("`).replace(/' target='_blank'/g, `")'`);
|
let text = this.currentNews.text;
|
||||||
|
if (STEAM) {
|
||||||
|
window.openNewsLink = openExternalLink;
|
||||||
|
text = text
|
||||||
|
.replace(/href='/gu, `onClick='window.openNewsLink("`)
|
||||||
|
.replace(/' target='_blank'/gu, `")'`);
|
||||||
|
}
|
||||||
|
line.innerHTML = text;
|
||||||
|
|
||||||
line.style["transition-duration"] = "0ms";
|
line.style["transition-duration"] = "0ms";
|
||||||
if (this.currentNews?.id === "a244" || this.currentNews?.id === "ai63") {
|
if (this.currentNews?.id === "a244" || this.currentNews?.id === "ai63") {
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
export const DEV = process.env.VUE_APP_DEV === "true";
|
export const DEV = process.env.VUE_APP_DEV === "true";
|
||||||
export const STEAM = process.env.VUE_APP_STEAM === "true";
|
export const STEAM = process.env.VUE_APP_STEAM === "true";
|
||||||
|
export const MAC = window.navigator.platform === "MacIntel";
|
||||||
|
@ -1303,7 +1303,7 @@ PlayFab.ClientApi = {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export var PlayFabClientSDK = PlayFab.ClientApi;
|
var PlayFabClientSDK = PlayFab.ClientApi;
|
||||||
|
|
||||||
PlayFab.RegisterWithPhaser = function() {
|
PlayFab.RegisterWithPhaser = function() {
|
||||||
if ( typeof Phaser === "undefined" || typeof Phaser.Plugin === "undefined" )
|
if ( typeof Phaser === "undefined" || typeof Phaser.Plugin === "undefined" )
|
24
src/steam/bindings/electron.js
Normal file
24
src/steam/bindings/electron.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { NodeModule } from "../node-module";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {NodeModule<any>}
|
||||||
|
*/
|
||||||
|
const module = new NodeModule("electron");
|
||||||
|
|
||||||
|
export function isModuleLoaded() {
|
||||||
|
return module.isLoaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setZoomFactor(zoomFactor) {
|
||||||
|
const setSize = 1020;
|
||||||
|
const sizeDiff = window.outerHeight / setSize;
|
||||||
|
return module.safeCall(
|
||||||
|
x => x.webFrame.setZoomFactor(sizeDiff * zoomFactor)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function openExternal(url) {
|
||||||
|
return module.safeCall(
|
||||||
|
x => x.shell.openExternal(url)
|
||||||
|
);
|
||||||
|
}
|
72
src/steam/bindings/greenworks.js
Normal file
72
src/steam/bindings/greenworks.js
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
import { NodeModule } from "../node-module";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {NodeModule<Greenworks.NodeModule>}
|
||||||
|
*/
|
||||||
|
const module = new NodeModule("greenworks");
|
||||||
|
|
||||||
|
export function isModuleLoaded() {
|
||||||
|
return module.isLoaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function initAPI() {
|
||||||
|
return module.safeCall(
|
||||||
|
x => x.initAPI(),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSteamId() {
|
||||||
|
return module.safeCall(
|
||||||
|
x => x.getSteamId()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {Promise<Greenworks.SteamAuthTicket>}
|
||||||
|
*/
|
||||||
|
export function getAuthSessionTicket() {
|
||||||
|
return module.makePromise(
|
||||||
|
(x, resolve, reject) => x.getAuthSessionTicket(resolve, reject)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
export function activateAchievement(id) {
|
||||||
|
return module.makePromise(
|
||||||
|
(x, resolve, reject) => x.activateAchievement(id, resolve, reject)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mako, please rename the second parameter. I have no idea what it is.
|
||||||
|
export function initDiscordAPI(clientId, steamGameId) {
|
||||||
|
return module.safeCall(
|
||||||
|
x => x.initDiscordAPI(clientId, steamGameId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function runDiscordCallbacks() {
|
||||||
|
return module.safeCall(
|
||||||
|
x => x.runDiscordCallbacks()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function on(event, callback) {
|
||||||
|
return module.safeCall(
|
||||||
|
x => x.on(event, callback)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setDiscordActivity(state, details) {
|
||||||
|
return module.safeCall(
|
||||||
|
x => x.setDiscordActivity({
|
||||||
|
smallImage: "icon",
|
||||||
|
largeImage: "icon",
|
||||||
|
state,
|
||||||
|
details
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
118
src/steam/bindings/playfab.js
Normal file
118
src/steam/bindings/playfab.js
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
import { PlayFab } from "@/steam/bindings/PlayFabClientApi";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {PlayFabClientModule.IPlayFabClient}
|
||||||
|
*/
|
||||||
|
const clientApi = PlayFab.ClientApi;
|
||||||
|
PlayFab.settings.titleId = "59813";
|
||||||
|
|
||||||
|
export function LoginWithSteam(ticket) {
|
||||||
|
return makePromise(clientApi.LoginWithSteam, {
|
||||||
|
SteamTicket: ticket,
|
||||||
|
CreateAccount: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function UpdateUserTitleDisplayName(displayName) {
|
||||||
|
makeAuthorizedPromise(clientApi.UpdateUserTitleDisplayName, {
|
||||||
|
DisplayName: displayName
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function GetUserData() {
|
||||||
|
return makeAuthorizedPromise(clientApi.GetUserData);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function UpdateUserData(data) {
|
||||||
|
return makeAuthorizedPromise(clientApi.UpdateUserData, {
|
||||||
|
Data: data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function GetUserInventory() {
|
||||||
|
return makeAuthorizedPromise(clientApi.GetUserInventory);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function PurchaseItem(id, price, currency) {
|
||||||
|
return makeAuthorizedPromise(clientApi.PurchaseItem, {
|
||||||
|
ItemId: id,
|
||||||
|
Price: price,
|
||||||
|
VirtualCurrency: currency
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function StartPurchase(itemId, quantity, annotation) {
|
||||||
|
return makeAuthorizedPromise(clientApi.StartPurchase, {
|
||||||
|
Items: [{
|
||||||
|
ItemId: itemId,
|
||||||
|
Quantity: quantity,
|
||||||
|
Annotation: annotation
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function PayForPurchase(orderId, currency, providerName) {
|
||||||
|
return makeAuthorizedPromise(clientApi.PayForPurchase, {
|
||||||
|
OrderId: orderId,
|
||||||
|
Currency: currency,
|
||||||
|
ProviderName: providerName
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ConfirmPurchase(orderId) {
|
||||||
|
return makeAuthorizedPromise(clientApi.ConfirmPurchase, {
|
||||||
|
OrderId: orderId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ConsumeItem(itemInstanceId, consumeCount) {
|
||||||
|
return makeAuthorizedPromise(clientApi.ConsumeItem, {
|
||||||
|
ItemInstanceId: itemInstanceId,
|
||||||
|
ConsumeCount: consumeCount
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function AddUserVirtualCurrency(amount, virtualCurrency) {
|
||||||
|
return makeAuthorizedPromise(clientApi.ConfirmPurchase, {
|
||||||
|
Amount: amount,
|
||||||
|
VirtualCurrency: virtualCurrency
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template TRequest
|
||||||
|
* @template TResponse
|
||||||
|
* @param {(request: TRequest, callback: PlayFabModule.ApiCallback<TResponse>) => any} playFabFunction
|
||||||
|
* @param {TRequest} [request]
|
||||||
|
* @returns {Promise<TResponse>}
|
||||||
|
*/
|
||||||
|
function makeAuthorizedPromise(playFabFunction, request) {
|
||||||
|
if (!clientApi.IsClientLoggedIn()) {
|
||||||
|
return Promise.reject("PlayFab Client is not logged in.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return makePromise(playFabFunction, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* So, apparently, PlayFab Web SDK is so bad, the promises they are
|
||||||
|
* returning are not the actual promises for the api calls
|
||||||
|
* (just take a look inside PlayFabClient.js). This wrapper
|
||||||
|
* creates proper promises based on the callbacks.
|
||||||
|
* @template TRequest
|
||||||
|
* @template TResponse
|
||||||
|
* @param {(request: TRequest, callback: PlayFabModule.ApiCallback<TResponse>) => any} playFabFunction
|
||||||
|
* @param {TRequest} [request]
|
||||||
|
* @returns {Promise<TResponse>}
|
||||||
|
*/
|
||||||
|
function makePromise(playFabFunction, request) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
playFabFunction(request ?? {}, (data, error) => {
|
||||||
|
if (!error && data?.data) {
|
||||||
|
resolve(data.data);
|
||||||
|
} else {
|
||||||
|
reject(error ?? data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
75
src/steam/electron-runtime.js
Normal file
75
src/steam/electron-runtime.js
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import * as Electron from "./bindings/electron";
|
||||||
|
|
||||||
|
const MIN_ZOOM = 0.5;
|
||||||
|
const MAX_ZOOM = 1.5;
|
||||||
|
|
||||||
|
let zoomFactor = 1;
|
||||||
|
|
||||||
|
export const ElectronRuntime = {
|
||||||
|
initialize() {
|
||||||
|
if (!this.isActive) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
zoomFactor = Number(localStorage.getItem("Zoom"));
|
||||||
|
zoomFactor = Number.isFinite(zoomFactor) ? zoomFactor : 1;
|
||||||
|
window.addEventListener("resize", () => this.updateZoom());
|
||||||
|
},
|
||||||
|
|
||||||
|
get isActive() {
|
||||||
|
return Electron.isModuleLoaded();
|
||||||
|
},
|
||||||
|
|
||||||
|
increaseZoom() {
|
||||||
|
if (!this.isActive) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zoomFactor > MAX_ZOOM) {
|
||||||
|
GameUI.notify.info("Zoom Level is at Maximum");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.zoomFactor = Math.round((zoomFactor + 0.1) * 10) / 10;
|
||||||
|
},
|
||||||
|
|
||||||
|
decreaseZoom() {
|
||||||
|
if (!this.isActive) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zoomFactor < MIN_ZOOM) {
|
||||||
|
GameUI.notify.info("Zoom Level is at Minimum");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.zoomFactor = Math.round((zoomFactor - 0.1) * 10) / 10;
|
||||||
|
},
|
||||||
|
|
||||||
|
resetZoom() {
|
||||||
|
if (!this.isActive) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.zoomFactor = 1;
|
||||||
|
},
|
||||||
|
|
||||||
|
get zoomFactor() {
|
||||||
|
return zoomFactor;
|
||||||
|
},
|
||||||
|
|
||||||
|
set zoomFactor(value) {
|
||||||
|
zoomFactor = value;
|
||||||
|
localStorage.setItem("Zoom", zoomFactor.toString());
|
||||||
|
this.updateZoom();
|
||||||
|
GameUI.notify.info(`Size changed to ${Math.round(zoomFactor * 100)}%`);
|
||||||
|
},
|
||||||
|
|
||||||
|
updateZoom() {
|
||||||
|
if (!this.isActive) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Electron.setZoomFactor(zoomFactor);
|
||||||
|
}
|
||||||
|
};
|
2
src/steam/index.js
Normal file
2
src/steam/index.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { ElectronRuntime } from "./electron-runtime";
|
||||||
|
export { SteamRuntime } from "./steam-runtime";
|
60
src/steam/node-module.js
Normal file
60
src/steam/node-module.js
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/* eslint-disable no-console */
|
||||||
|
|
||||||
|
import { STEAM } from "@/env";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template TModule
|
||||||
|
*/
|
||||||
|
export class NodeModule {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} name
|
||||||
|
*/
|
||||||
|
constructor(name) {
|
||||||
|
this.name = name;
|
||||||
|
/**
|
||||||
|
* @type {TModule}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.__module__ = STEAM && window.require !== undefined ? window.require(name) : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
get isLoaded() {
|
||||||
|
return this.__module__ !== undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template TResult
|
||||||
|
* @param {(module: TModule, resolve: (value?: TResult) => void, reject: (reason?: any) => void) => void} executor
|
||||||
|
* @returns {Promise<TResult>}
|
||||||
|
*/
|
||||||
|
makePromise(executor) {
|
||||||
|
if (!this.isLoaded) {
|
||||||
|
throw Error(`Node module "${this.name}" is not loaded.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
executor(this.__module__, resolve, reject);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template TResult
|
||||||
|
* @param {(module: TModule) => TResult} call
|
||||||
|
* @param {TResult} [defaultValue]
|
||||||
|
* @returns {TResult}
|
||||||
|
*/
|
||||||
|
safeCall(call, defaultValue) {
|
||||||
|
if (!this.isLoaded) {
|
||||||
|
throw Error(`Node module "${this.name}" is not loaded.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return call(this.__module__);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`Failed to make a call to node module "${this.name}".`);
|
||||||
|
console.error(e);
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
99
src/steam/steam-purchases.js
Normal file
99
src/steam/steam-purchases.js
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
import { MAC } from "@/env";
|
||||||
|
import { openExternalLink } from "@/utility/open-external-link";
|
||||||
|
import * as PlayFab from "./bindings/playfab";
|
||||||
|
|
||||||
|
let pendingConfirmations = [];
|
||||||
|
|
||||||
|
export function hasPendingPurchaseConfirmations() {
|
||||||
|
return MAC && pendingConfirmations.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function purchaseIap(std) {
|
||||||
|
const itemId = `${std}STD`;
|
||||||
|
const quantity = 1;
|
||||||
|
const annotation = "Purchased via in-game store";
|
||||||
|
const order = await PlayFab.StartPurchase(itemId, quantity, annotation);
|
||||||
|
|
||||||
|
const orderId = order.OrderId;
|
||||||
|
const currency = "RM";
|
||||||
|
const providerName = "Steam";
|
||||||
|
const result = await PlayFab.PayForPurchase(orderId, currency, providerName);
|
||||||
|
|
||||||
|
pendingConfirmations.push(result.OrderId);
|
||||||
|
|
||||||
|
if (MAC) {
|
||||||
|
const txnId = result.ProviderData;
|
||||||
|
openExternalLink(`https://store.steampowered.com/checkout/approvetxn/${txnId}/?returnurl=steam`);
|
||||||
|
|
||||||
|
const macInterval = setInterval(() => {
|
||||||
|
validatePurchases();
|
||||||
|
}, 2000);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
clearInterval(macInterval);
|
||||||
|
}, 300000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function validatePurchases() {
|
||||||
|
for (const order of pendingConfirmations) {
|
||||||
|
validatePurchase(order);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function validatePurchase(orderId) {
|
||||||
|
const confirm = await PlayFab.ConfirmPurchase(orderId);
|
||||||
|
const purchaseName = confirm.Items[0].ItemId;
|
||||||
|
const purchaseInstance = confirm.Items[0].ItemInstanceId;
|
||||||
|
|
||||||
|
await PlayFab.ConsumeItem(purchaseInstance, 1);
|
||||||
|
const stdsBought = Number(purchaseName.replace("STD", ""));
|
||||||
|
pendingConfirmations = pendingConfirmations.filter(item => item !== orderId);
|
||||||
|
await PlayFab.AddUserVirtualCurrency(stdsBought, "ST");
|
||||||
|
GameUI.notify.info(`${stdsBought} STDs Obtained!`);
|
||||||
|
syncIap();
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function syncIap() {
|
||||||
|
const userInventory = await PlayFab.GetUserInventory();
|
||||||
|
ShopPurchaseData.totalSTD = userInventory.VirtualCurrency?.ST ?? 0;
|
||||||
|
for (const key of Object.keys(GameDatabase.shopPurchases)) {
|
||||||
|
const item = userInventory.Inventory.find(x => x.ItemId === key);
|
||||||
|
ShopPurchaseData[key] = item?.RemainingUses ?? 0;
|
||||||
|
}
|
||||||
|
GameUI.update();
|
||||||
|
|
||||||
|
const userData = await PlayFab.GetUserData();
|
||||||
|
ShopPurchaseData.unlockedCosmetics = userData.Data.Cosmetics?.Value?.split(",") ?? [];
|
||||||
|
GameUI.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function purchaseShopItem(key, cost, cosmeticName) {
|
||||||
|
await PlayFab.PurchaseItem(key, cost, "ST");
|
||||||
|
await storeCosmetic(cosmeticName);
|
||||||
|
syncIap();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function storeCosmetic(name) {
|
||||||
|
if (name === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cosmetic = Object.values(GameDatabase.reality.glyphCosmeticSets)
|
||||||
|
.find(x => x.name === name);
|
||||||
|
if (cosmetic === undefined) {
|
||||||
|
GameUI.notify.error(`Failed to store cosmetic "${name}"`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const userData = await PlayFab.GetUserData();
|
||||||
|
const cosmetics = new Set(userData.Data?.Cosmetics?.Value?.split(",") ?? []);
|
||||||
|
cosmetics.add(cosmetic.id);
|
||||||
|
const updatedCosmetics = [...cosmetics];
|
||||||
|
await PlayFab.UpdateUserData({
|
||||||
|
Cosmetics: updatedCosmetics.join(",")
|
||||||
|
});
|
||||||
|
|
||||||
|
ShopPurchaseData.unlockedCosmetics = updatedCosmetics;
|
||||||
|
GameUI.update();
|
||||||
|
}
|
178
src/steam/steam-runtime.js
Normal file
178
src/steam/steam-runtime.js
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
/* eslint-disable no-console */
|
||||||
|
import { RichPresenceInfo } from "../../javascripts/core/discord-parser";
|
||||||
|
|
||||||
|
import {
|
||||||
|
hasPendingPurchaseConfirmations,
|
||||||
|
purchaseIap,
|
||||||
|
purchaseShopItem,
|
||||||
|
syncIap,
|
||||||
|
validatePurchases
|
||||||
|
} from "./steam-purchases";
|
||||||
|
|
||||||
|
import * as Greenworks from "./bindings/greenworks";
|
||||||
|
import * as PlayFab from "./bindings/playfab";
|
||||||
|
|
||||||
|
import { MAC, STEAM } from "@/env";
|
||||||
|
|
||||||
|
let isInitialized = false;
|
||||||
|
let isActive = false;
|
||||||
|
|
||||||
|
export const SteamRuntime = {
|
||||||
|
initialize() {
|
||||||
|
if (isInitialized) {
|
||||||
|
throw Error("Steam Runtime was initialized already.");
|
||||||
|
}
|
||||||
|
|
||||||
|
isInitialized = true;
|
||||||
|
|
||||||
|
if (!STEAM || !Greenworks.isModuleLoaded() || !Greenworks.initAPI()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
isActive = true;
|
||||||
|
|
||||||
|
const steamId = Greenworks.getSteamId();
|
||||||
|
loginPlayFab(steamId);
|
||||||
|
loginFirebase(steamId);
|
||||||
|
|
||||||
|
Greenworks.on("micro-txn-authorization-response", (data, ordered, orderstate) => {
|
||||||
|
if (orderstate === true) {
|
||||||
|
validatePurchases();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!MAC) {
|
||||||
|
initializeDiscord();
|
||||||
|
}
|
||||||
|
|
||||||
|
createForceRefreshCanvas();
|
||||||
|
},
|
||||||
|
|
||||||
|
get isActive() {
|
||||||
|
if (!isInitialized) {
|
||||||
|
throw Error("Steam Runtime was called before init.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return isActive;
|
||||||
|
},
|
||||||
|
|
||||||
|
get screenName() {
|
||||||
|
if (!this.isActive) {
|
||||||
|
return "Non-Steam user";
|
||||||
|
}
|
||||||
|
|
||||||
|
return Greenworks.getSteamId()?.screenName ?? "Steam user";
|
||||||
|
},
|
||||||
|
|
||||||
|
activateAchievement(id) {
|
||||||
|
if (!this.isActive) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Greenworks.activateAchievement(`Achievement${id}`);
|
||||||
|
},
|
||||||
|
|
||||||
|
async purchaseIap(std) {
|
||||||
|
if (!this.isActive) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await purchaseIap(std);
|
||||||
|
},
|
||||||
|
|
||||||
|
validatePurchases() {
|
||||||
|
if (!this.isActive) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
validatePurchases();
|
||||||
|
},
|
||||||
|
|
||||||
|
async syncIap() {
|
||||||
|
if (!this.isActive) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await syncIap();
|
||||||
|
},
|
||||||
|
|
||||||
|
async purchaseShopItem(key, cost, cosmeticName) {
|
||||||
|
if (!this.isActive) {
|
||||||
|
GameUI.notify.error("Shop purchases are not available.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await purchaseShopItem(key, cost, cosmeticName);
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
GameUI.notify.error(e.errorMessage ?? e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
get hasPendingPurchaseConfirmations() {
|
||||||
|
if (!this.isActive) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hasPendingPurchaseConfirmations();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
async function loginPlayFab(steamId) {
|
||||||
|
try {
|
||||||
|
const screenName = steamId.screenName;
|
||||||
|
const ticket = await Greenworks.getAuthSessionTicket();
|
||||||
|
await PlayFab.LoginWithSteam(ticket.ticket.toString("hex"), screenName);
|
||||||
|
PlayFab.UpdateUserTitleDisplayName(screenName);
|
||||||
|
GameUI.notify.info("Logged in to PlayFab Cloud");
|
||||||
|
} catch (error) {
|
||||||
|
GameUI.notify.error("Couldn't log in to PlayFab Cloud.");
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loginFirebase(steamId) {
|
||||||
|
const accountId = steamId.accountId;
|
||||||
|
const staticAccountId = steamId.staticAccountId;
|
||||||
|
const screenName = steamId.screenName;
|
||||||
|
if (await Cloud.loginWithSteam(accountId, staticAccountId, screenName)) {
|
||||||
|
syncIap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function initializeDiscord() {
|
||||||
|
Greenworks.initDiscordAPI("1057439416819396689", 1399720);
|
||||||
|
setDiscordActivity();
|
||||||
|
Greenworks.runDiscordCallbacks();
|
||||||
|
setInterval(setDiscordActivity, 8000);
|
||||||
|
setInterval(Greenworks.runDiscordCallbacks, 4000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setDiscordActivity() {
|
||||||
|
Greenworks.setDiscordActivity(RichPresenceInfo.state, RichPresenceInfo.details);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createForceRefreshCanvas() {
|
||||||
|
// This canvas is required for Steam overlay to properly work in Electron.
|
||||||
|
// Makopaz:
|
||||||
|
// "essentially it makes the overlay have a refresh rate, otherwise it only
|
||||||
|
// updates based on parts of the screen which change, so without it the small
|
||||||
|
// areas of the screen where antimatter and such increment would be the only
|
||||||
|
// small portions of the overlay showing."
|
||||||
|
// There should be a less expensive approach. Please create a new issue or
|
||||||
|
// PR on GitHub if you know one, the planet will say thank you for saving
|
||||||
|
// megawatts of electricity spent on this canvas.
|
||||||
|
const canvas = document.createElement("canvas");
|
||||||
|
canvas.classList.add("_steam-refresh-canvas");
|
||||||
|
document.body.appendChild(canvas);
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
|
||||||
|
function forceRefresh() {
|
||||||
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
window.requestAnimationFrame(forceRefresh);
|
||||||
|
}
|
||||||
|
|
||||||
|
forceRefresh();
|
||||||
|
}
|
5731
src/typings/PlayFabClientApi.d.ts
vendored
Normal file
5731
src/typings/PlayFabClientApi.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
82
src/typings/Playfab.d.ts
vendored
Normal file
82
src/typings/Playfab.d.ts
vendored
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/// <reference path="PlayFabAdminApi.d.ts" />
|
||||||
|
/// <reference path="PlayFabClientApi.d.ts" />
|
||||||
|
/// <reference path="PlayFabMatchmakerApi.d.ts" />
|
||||||
|
/// <reference path="PlayFabServerApi.d.ts" />
|
||||||
|
/// <reference path="PlayFabAuthenticationApi.d.ts" />
|
||||||
|
/// <reference path="PlayFabCloudScriptApi.d.ts" />
|
||||||
|
/// <reference path="PlayFabDataApi.d.ts" />
|
||||||
|
/// <reference path="PlayFabEconomyApi.d.ts" />
|
||||||
|
/// <reference path="PlayFabEventsApi.d.ts" />
|
||||||
|
/// <reference path="PlayFabExperimentationApi.d.ts" />
|
||||||
|
/// <reference path="PlayFabInsightsApi.d.ts" />
|
||||||
|
/// <reference path="PlayFabGroupsApi.d.ts" />
|
||||||
|
/// <reference path="PlayFabLocalizationApi.d.ts" />
|
||||||
|
/// <reference path="PlayFabMultiplayerApi.d.ts" />
|
||||||
|
/// <reference path="PlayFabProfilesApi.d.ts" />
|
||||||
|
|
||||||
|
declare module PlayFabModule {
|
||||||
|
export interface ISettings {
|
||||||
|
titleId: string;
|
||||||
|
developerSecretKey: string;
|
||||||
|
GlobalHeaderInjection?: { [key: string]: string };
|
||||||
|
productionServerUrl: string;
|
||||||
|
}
|
||||||
|
export interface IPlayFabRequestCommon { }
|
||||||
|
export interface IPlayFabError {
|
||||||
|
code: number;
|
||||||
|
status: string;
|
||||||
|
error: string;
|
||||||
|
errorCode: number;
|
||||||
|
errorMessage: string;
|
||||||
|
errorDetails?: { [key: string]: string[] };
|
||||||
|
request?: any;
|
||||||
|
customData?: any;
|
||||||
|
retryAfterSeconds?: number;
|
||||||
|
}
|
||||||
|
export interface SuccessContainer<TResult extends IPlayFabResultCommon> extends IPlayFabError {
|
||||||
|
data: TResult;
|
||||||
|
}
|
||||||
|
export interface IPlayFabResultCommon extends IPlayFabError { }
|
||||||
|
|
||||||
|
export interface ApiCallback<TResult extends IPlayFabResultCommon> { (result: SuccessContainer<TResult>, error: IPlayFabError): void }
|
||||||
|
}
|
||||||
|
|
||||||
|
declare var PlayFab: {
|
||||||
|
buildIdentifier: string;
|
||||||
|
sdkVersion: string;
|
||||||
|
GenerateErrorReport(IPlayFabError): string;
|
||||||
|
settings: PlayFabModule.ISettings;
|
||||||
|
AdminApi: PlayFabAdminModule.IPlayFabAdmin;
|
||||||
|
ClientApi: PlayFabClientModule.IPlayFabClient;
|
||||||
|
MatchmakerApi: PlayFabMatchmakerModule.IPlayFabMatchmaker;
|
||||||
|
ServerApi: PlayFabServerModule.IPlayFabServer;
|
||||||
|
AuthenticationApi: PlayFabAuthenticationModule.IPlayFabAuthentication;
|
||||||
|
CloudScriptApi: PlayFabCloudScriptModule.IPlayFabCloudScript;
|
||||||
|
DataApi: PlayFabDataModule.IPlayFabData;
|
||||||
|
EconomyApi: PlayFabEconomyModule.IPlayFabEconomy;
|
||||||
|
EventsApi: PlayFabEventsModule.IPlayFabEvents;
|
||||||
|
ExperimentationApi: PlayFabExperimentationModule.IPlayFabExperimentation;
|
||||||
|
InsightsApi: PlayFabInsightsModule.IPlayFabInsights;
|
||||||
|
GroupsApi: PlayFabGroupsModule.IPlayFabGroups;
|
||||||
|
LocalizationApi: PlayFabLocalizationModule.IPlayFabLocalization;
|
||||||
|
MultiplayerApi: PlayFabMultiplayerModule.IPlayFabMultiplayer;
|
||||||
|
ProfilesApi: PlayFabProfilesModule.IPlayFabProfiles;
|
||||||
|
|
||||||
|
};
|
||||||
|
// Continue to support older usage
|
||||||
|
declare var PlayFabAdminSDK: PlayFabAdminModule.IPlayFabAdmin;
|
||||||
|
declare var PlayFabClientSDK: PlayFabClientModule.IPlayFabClient;
|
||||||
|
declare var PlayFabMatchmakerSDK: PlayFabMatchmakerModule.IPlayFabMatchmaker;
|
||||||
|
declare var PlayFabServerSDK: PlayFabServerModule.IPlayFabServer;
|
||||||
|
declare var PlayFabAuthenticationSDK: PlayFabAuthenticationModule.IPlayFabAuthentication;
|
||||||
|
declare var PlayFabCloudScriptSDK: PlayFabCloudScriptModule.IPlayFabCloudScript;
|
||||||
|
declare var PlayFabDataSDK: PlayFabDataModule.IPlayFabData;
|
||||||
|
declare var PlayFabEconomySDK: PlayFabEconomyModule.IPlayFabEconomy;
|
||||||
|
declare var PlayFabEventsSDK: PlayFabEventsModule.IPlayFabEvents;
|
||||||
|
declare var PlayFabExperimentationSDK: PlayFabExperimentationModule.IPlayFabExperimentation;
|
||||||
|
declare var PlayFabInsightsSDK: PlayFabInsightsModule.IPlayFabInsights;
|
||||||
|
declare var PlayFabGroupsSDK: PlayFabGroupsModule.IPlayFabGroups;
|
||||||
|
declare var PlayFabLocalizationSDK: PlayFabLocalizationModule.IPlayFabLocalization;
|
||||||
|
declare var PlayFabMultiplayerSDK: PlayFabMultiplayerModule.IPlayFabMultiplayer;
|
||||||
|
declare var PlayFabProfilesSDK: PlayFabProfilesModule.IPlayFabProfiles;
|
||||||
|
|
30
src/typings/greenworks.d.ts
vendored
Normal file
30
src/typings/greenworks.d.ts
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
export declare module Greenworks {
|
||||||
|
export interface NodeModule {
|
||||||
|
initAPI(): boolean;
|
||||||
|
getSteamId(): SteamId;
|
||||||
|
getAuthSessionTicket(resolve: (ticket: SteamAuthTicket) => void, reject: (error: any) => void): void;
|
||||||
|
activateAchievement(id: string, resolve: () => void, reject: (error: any) => void): void;
|
||||||
|
initDiscordAPI(clientId: string, steamGameId: number): void;
|
||||||
|
runDiscordCallbacks(): void;
|
||||||
|
setDiscordActivity(info: DiscordActivityInfo): void;
|
||||||
|
on(event: string, callback: Function): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SteamId {
|
||||||
|
screenName: string;
|
||||||
|
accountId: string;
|
||||||
|
staticAccountId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SteamAuthTicket {
|
||||||
|
ticket: Buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DiscordActivityInfo {
|
||||||
|
largeImage: string;
|
||||||
|
smallImage: string;
|
||||||
|
details: string;
|
||||||
|
state: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
9
src/utility/open-external-link.js
Normal file
9
src/utility/open-external-link.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import * as Electron from "@/steam/bindings/electron";
|
||||||
|
|
||||||
|
export function openExternalLink(url) {
|
||||||
|
if (Electron.isModuleLoaded()) {
|
||||||
|
Electron.openExternal(url);
|
||||||
|
} else {
|
||||||
|
window.open(url, "_blank").focus();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user