achievements

This commit is contained in:
Olivier Gagnon 2021-11-27 15:07:25 -05:00
parent d257cb84ad
commit e262c9bb38
21 changed files with 409 additions and 44 deletions

34
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

217
electron/greenworks.js Normal file

@ -0,0 +1,217 @@
// Copyright (c) 2015 Greenheart Games Pty. Ltd. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
// The source code can be found in https://github.com/greenheartgames/greenworks
var fs = require('fs');
var greenworks;
if (process.platform == 'darwin') {
if (process.arch == 'x64')
greenworks = require('./lib/greenworks-osx64');
else if (process.arch == 'ia32')
greenworks = require('./lib/greenworks-osx32');
} else if (process.platform == 'win32') {
if (process.arch == 'x64')
greenworks = require('./lib/greenworks-win64');
else if (process.arch == 'ia32')
greenworks = require('./lib/greenworks-win32');
} else if (process.platform == 'linux') {
if (process.arch == 'x64')
greenworks = require('./lib/greenworks-linux64');
else if (process.arch == 'ia32')
greenworks = require('./lib/greenworks-linux32');
}
function error_process(err, error_callback) {
if (err && error_callback)
error_callback(err);
}
greenworks.ugcGetItems = function(options, ugc_matching_type, ugc_query_type,
success_callback, error_callback) {
if (typeof options !== 'object') {
error_callback = success_callback;
success_callback = ugc_query_type;
ugc_query_type = ugc_matching_type;
ugc_matching_type = options;
options = {
'app_id': greenworks.getAppId(),
'page_num': 1
}
}
greenworks._ugcGetItems(options, ugc_matching_type, ugc_query_type,
success_callback, error_callback);
}
greenworks.ugcGetUserItems = function(options, ugc_matching_type,
ugc_list_sort_order, ugc_list, success_callback, error_callback) {
if (typeof options !== 'object') {
error_callback = success_callback;
success_callback = ugc_list;
ugc_list = ugc_list_sort_order;
ugc_list_sort_order = ugc_matching_type;
ugc_matching_type = options;
options = {
'app_id': greenworks.getAppId(),
'page_num': 1
}
}
greenworks._ugcGetUserItems(options, ugc_matching_type, ugc_list_sort_order,
ugc_list, success_callback, error_callback);
}
greenworks.ugcSynchronizeItems = function (options, sync_dir, success_callback,
error_callback) {
if (typeof options !== 'object') {
error_callback = success_callback;
success_callback = sync_dir;
sync_dir = options;
options = {
'app_id': greenworks.getAppId(),
'page_num': 1
}
}
greenworks._ugcSynchronizeItems(options, sync_dir, success_callback,
error_callback);
}
greenworks.publishWorkshopFile = function(options, file_path, image_path, title,
description, success_callback, error_callback) {
if (typeof options !== 'object') {
error_callback = success_callback;
success_callback = description;
description = title;
title = image_path;
image_path = file_path;
file_path = options;
options = {
'app_id': greenworks.getAppId(),
'tags': []
}
}
greenworks._publishWorkshopFile(options, file_path, image_path, title,
description, success_callback, error_callback);
}
greenworks.updatePublishedWorkshopFile = function(options,
published_file_handle, file_path, image_path, title, description,
success_callback, error_callback) {
if (typeof options !== 'object') {
error_callback = success_callback;
success_callback = description;
description = title;
title = image_path;
image_path = file_path;
file_path = published_file_handle;
published_file_handle = options;
options = {
'tags': [] // No tags are set
}
}
greenworks._updatePublishedWorkshopFile(options, published_file_handle,
file_path, image_path, title, description, success_callback,
error_callback);
}
// An utility function for publish related APIs.
// It processes remains steps after saving files to Steam Cloud.
function file_share_process(file_name, image_name, next_process_func,
error_callback, progress_callback) {
if (progress_callback)
progress_callback("Completed on saving files on Steam Cloud.");
greenworks.fileShare(file_name, function() {
greenworks.fileShare(image_name, function() {
next_process_func();
}, function(err) { error_process(err, error_callback); });
}, function(err) { error_process(err, error_callback); });
}
// Publishing user generated content(ugc) to Steam contains following steps:
// 1. Save file and image to Steam Cloud.
// 2. Share the file and image.
// 3. publish the file to workshop.
greenworks.ugcPublish = function(file_name, title, description, image_name,
success_callback, error_callback, progress_callback) {
var publish_file_process = function() {
if (progress_callback)
progress_callback("Completed on sharing files.");
greenworks.publishWorkshopFile(file_name, image_name, title, description,
function(publish_file_id) { success_callback(publish_file_id); },
function(err) { error_process(err, error_callback); });
};
greenworks.saveFilesToCloud([file_name, image_name], function() {
file_share_process(file_name, image_name, publish_file_process,
error_callback, progress_callback);
}, function(err) { error_process(err, error_callback); });
}
// Update publish ugc steps:
// 1. Save new file and image to Steam Cloud.
// 2. Share file and images.
// 3. Update published file.
greenworks.ugcPublishUpdate = function(published_file_id, file_name, title,
description, image_name, success_callback, error_callback,
progress_callback) {
var update_published_file_process = function() {
if (progress_callback)
progress_callback("Completed on sharing files.");
greenworks.updatePublishedWorkshopFile(published_file_id,
file_name, image_name, title, description,
function() { success_callback(); },
function(err) { error_process(err, error_callback); });
};
greenworks.saveFilesToCloud([file_name, image_name], function() {
file_share_process(file_name, image_name, update_published_file_process,
error_callback, progress_callback);
}, function(err) { error_process(err, error_callback); });
}
// Greenworks Utils APIs implmentation.
greenworks.Utils.move = function(source_dir, target_dir, success_callback,
error_callback) {
fs.rename(source_dir, target_dir, function(err) {
if (err) {
if (error_callback) error_callback(err);
return;
}
if (success_callback)
success_callback();
});
}
greenworks.init = function() {
if (this.initAPI()) return true;
if (!this.isSteamRunning())
throw new Error("Steam initialization failed. Steam is not running.");
var appId;
try {
appId = fs.readFileSync('steam_appid.txt', 'utf8');
} catch (e) {
throw new Error("Steam initialization failed. Steam is running," +
"but steam_appid.txt is missing. Expected to find it in: " +
require('path').resolve('steam_appid.txt'));
}
if (!/^\d+ *\r?\n?$/.test(appId)) {
throw new Error("Steam initialization failed. " +
"steam_appid.txt appears to be invalid; " +
"it should contain a numeric ID: " + appId);
}
throw new Error("Steam initialization failed, but Steam is running, " +
"and steam_appid.txt is present and valid." +
"Maybe that's not really YOUR app ID? " + appId.trim());
}
var EventEmitter = require('events').EventEmitter;
greenworks.__proto__ = EventEmitter.prototype;
EventEmitter.call(greenworks);
greenworks._steam_events.on = function () {
greenworks.emit.apply(greenworks, arguments);
};
process.versions['greenworks'] = greenworks._version;
module.exports = greenworks;

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
electron/lib/steam_api.dll Normal file

Binary file not shown.

BIN
electron/lib/steam_api.lib Normal file

Binary file not shown.

@ -0,0 +1 @@
1812820

@ -1,6 +1,14 @@
const { app, BrowserWindow, Menu, globalShortcut, shell } = require("electron"); const { app, BrowserWindow, Menu, globalShortcut, shell } = require("electron");
const greenworks = require("./greenworks");
const debug = false; if (greenworks.init()) {
console.log("Steam API has been initialized.");
greenworks.activateAchievement("BN1.1", () => undefined);
} else {
console.log("Steam API has failed to initialize.");
}
const debug = true;
Menu.setApplicationMenu(false); Menu.setApplicationMenu(false);
function createWindow() { function createWindow() {
@ -33,6 +41,11 @@ function createWindow() {
e.preventDefault(); e.preventDefault();
shell.openExternal(url); shell.openExternal(url);
}); });
setInterval(async () => {
const resp = await win.webContents.executeJavaScript("document.saveString");
await win.webContents.executeJavaScript(`console.log('${resp}')`);
}, 1000);
} }
app.whenReady().then(() => { app.whenReady().then(() => {

1
electron/steam_appid.txt Normal file

@ -0,0 +1 @@
1812820

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

40
package-lock.json generated

@ -1,11 +1,11 @@
{ {
"name": "bitburner", "name": "bitburner",
"version": "1.0.0", "version": "1.0.2",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"version": "1.0.0", "version": "1.0.2",
"hasInstallScript": true, "hasInstallScript": true,
"license": "SEE LICENSE IN license.txt", "license": "SEE LICENSE IN license.txt",
"dependencies": { "dependencies": {
@ -29,9 +29,9 @@
"better-react-mathjax": "^1.0.3", "better-react-mathjax": "^1.0.3",
"clsx": "^1.1.1", "clsx": "^1.1.1",
"date-fns": "^2.25.0", "date-fns": "^2.25.0",
"decimal.js": "7.2.3",
"escodegen": "^1.11.0", "escodegen": "^1.11.0",
"file-saver": "^1.3.8", "file-saver": "^1.3.8",
"fs": "^0.0.1-security",
"jquery": "^3.5.0", "jquery": "^3.5.0",
"jszip": "^3.7.0", "jszip": "^3.7.0",
"material-ui-color": "^1.2.0", "material-ui-color": "^1.2.0",
@ -59,7 +59,7 @@
"babel-jest": "^27.0.6", "babel-jest": "^27.0.6",
"babel-loader": "^8.0.5", "babel-loader": "^8.0.5",
"cypress": "^8.3.1", "cypress": "^8.3.1",
"electron": "^14.0.1", "electron": "^14.0.2",
"electron-packager": "^15.4.0", "electron-packager": "^15.4.0",
"eslint": "^7.24.0", "eslint": "^7.24.0",
"fork-ts-checker-webpack-plugin": "^6.3.3", "fork-ts-checker-webpack-plugin": "^6.3.3",
@ -7012,11 +7012,6 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/decimal.js": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-7.2.3.tgz",
"integrity": "sha512-AoFI37QS0S87Ft0r3Bdz4q9xSpm1Paa9lSeKLXgMPk/u/+QPIM5Gy4DHcZQS1seqPJH4gHLauPGn347z0HbsrA=="
},
"node_modules/decode-uri-component": { "node_modules/decode-uri-component": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
@ -7579,9 +7574,9 @@
"dev": true "dev": true
}, },
"node_modules/electron": { "node_modules/electron": {
"version": "14.1.1", "version": "14.0.2",
"resolved": "https://registry.npmjs.org/electron/-/electron-14.1.1.tgz", "resolved": "https://registry.npmjs.org/electron/-/electron-14.0.2.tgz",
"integrity": "sha512-eaqaxMq/auE5VDIzYYqDUgZg+68Uiv+8jAQUXqLh8G58kOxqRL9Jw4TJ/w2/KXwWGaVPaUStbvO9BtqVZant+A==", "integrity": "sha512-LIJj795cfggUtLHIM84lseE7LC0kAs/HNVXoDFPTjtYzQikPX9XAIMI1BTJcod3j+U1ZXsayk9N4M3M890WD3w==",
"dev": true, "dev": true,
"hasInstallScript": true, "hasInstallScript": true,
"dependencies": { "dependencies": {
@ -9609,6 +9604,11 @@
"safe-buffer": "~5.1.0" "safe-buffer": "~5.1.0"
} }
}, },
"node_modules/fs": {
"version": "0.0.1-security",
"resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz",
"integrity": "sha1-invTcYa23d84E/I4WLV+yq9eQdQ="
},
"node_modules/fs-extra": { "node_modules/fs-extra": {
"version": "9.1.0", "version": "9.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
@ -27035,11 +27035,6 @@
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
"dev": true "dev": true
}, },
"decimal.js": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-7.2.3.tgz",
"integrity": "sha512-AoFI37QS0S87Ft0r3Bdz4q9xSpm1Paa9lSeKLXgMPk/u/+QPIM5Gy4DHcZQS1seqPJH4gHLauPGn347z0HbsrA=="
},
"decode-uri-component": { "decode-uri-component": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
@ -27509,9 +27504,9 @@
"dev": true "dev": true
}, },
"electron": { "electron": {
"version": "14.1.1", "version": "14.0.2",
"resolved": "https://registry.npmjs.org/electron/-/electron-14.1.1.tgz", "resolved": "https://registry.npmjs.org/electron/-/electron-14.0.2.tgz",
"integrity": "sha512-eaqaxMq/auE5VDIzYYqDUgZg+68Uiv+8jAQUXqLh8G58kOxqRL9Jw4TJ/w2/KXwWGaVPaUStbvO9BtqVZant+A==", "integrity": "sha512-LIJj795cfggUtLHIM84lseE7LC0kAs/HNVXoDFPTjtYzQikPX9XAIMI1BTJcod3j+U1ZXsayk9N4M3M890WD3w==",
"dev": true, "dev": true,
"requires": { "requires": {
"@electron/get": "^1.0.1", "@electron/get": "^1.0.1",
@ -29108,6 +29103,11 @@
} }
} }
}, },
"fs": {
"version": "0.0.1-security",
"resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz",
"integrity": "sha1-invTcYa23d84E/I4WLV+yq9eQdQ="
},
"fs-extra": { "fs-extra": {
"version": "9.1.0", "version": "9.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",

@ -32,6 +32,7 @@
"date-fns": "^2.25.0", "date-fns": "^2.25.0",
"escodegen": "^1.11.0", "escodegen": "^1.11.0",
"file-saver": "^1.3.8", "file-saver": "^1.3.8",
"fs": "^0.0.1-security",
"jquery": "^3.5.0", "jquery": "^3.5.0",
"jszip": "^3.7.0", "jszip": "^3.7.0",
"material-ui-color": "^1.2.0", "material-ui-color": "^1.2.0",
@ -60,7 +61,7 @@
"babel-jest": "^27.0.6", "babel-jest": "^27.0.6",
"babel-loader": "^8.0.5", "babel-loader": "^8.0.5",
"cypress": "^8.3.1", "cypress": "^8.3.1",
"electron": "^14.0.1", "electron": "^14.0.2",
"electron-packager": "^15.4.0", "electron-packager": "^15.4.0",
"eslint": "^7.24.0", "eslint": "^7.24.0",
"fork-ts-checker-webpack-plugin": "^6.3.3", "fork-ts-checker-webpack-plugin": "^6.3.3",

127
src/Electron.tsx Normal file

@ -0,0 +1,127 @@
import { AugmentationNames } from "./Augmentation/data/AugmentationNames";
import { Exploit } from "./Exploits/Exploit";
import { Player } from "./Player";
interface Achievement {
ID: string;
Condition: () => boolean;
}
function sfAchievement(): Achievement[] {
const achs: Achievement[] = [];
for (let i = 0; i <= 11; i++) {
for (let j = 1; j <= 3; j++) {
achs.push({
ID: `SF${i}.${j}`,
Condition: () => Player.sourceFileLvl(i) >= j,
});
}
}
return achs;
}
const achievements: Achievement[] = [
{
ID: `UNACHIEVABLE`,
Condition: () => false,
},
...sfAchievement(),
{
ID: `SF12.100`,
Condition: () => Player.sourceFileLvl(12) >= 100,
},
{ ID: "BYPASS", Condition: () => Player.exploits.includes(Exploit.Bypass) },
{ ID: "PROTOTYPETAMPERING", Condition: () => Player.exploits.includes(Exploit.PrototypeTampering) },
{ ID: "UNCLICKABLE", Condition: () => Player.exploits.includes(Exploit.Unclickable) },
{ ID: "UNDOCUMENTEDFUNCTIONCALL", Condition: () => Player.exploits.includes(Exploit.UndocumentedFunctionCall) },
{ ID: "TIMECOMPRESSION", Condition: () => Player.exploits.includes(Exploit.TimeCompression) },
{ ID: "REALITYALTERATION", Condition: () => Player.exploits.includes(Exploit.RealityAlteration) },
{ ID: "N00DLES", Condition: () => Player.exploits.includes(Exploit.N00dles) },
{ ID: "EDITSAVEFILE", Condition: () => Player.exploits.includes(Exploit.EditSaveFile) },
{
ID: "MONEY_1Q",
Condition: () => Player.money >= 1e18,
},
{
ID: "MONEY_M1B",
Condition: () => Player.money <= -1e9,
},
{
ID: "INSTALL_1",
Condition: () => Player.augmentations.length >= 1,
},
{
ID: "INSTALL_100",
Condition: () => Player.augmentations.length >= 100,
},
{
ID: "QUEUE_40",
Condition: () => Player.queuedAugmentations.length >= 40,
},
{
ID: "SLEEVE_8",
Condition: () => Player.sleeves.length === 8,
},
{
ID: "HACKING_100000",
Condition: () => Player.hacking >= 100000,
},
{
ID: "INTELLIGENCE_100",
Condition: () => Player.intelligence >= 100,
},
{
ID: "COMBAT_1000",
Condition: () =>
Player.strength >= 1000 && Player.defense >= 1000 && Player.dexterity >= 1000 && Player.agility >= 1000,
},
{
ID: "NEUROFLUX_255",
Condition: () => Player.augmentations.some((a) => a.name === AugmentationNames.NeuroFluxGovernor && a.level >= 255),
},
{ ID: "ILLUMINATI", Condition: () => Player.factions.includes("Illuminati") },
{ ID: "DAEDALUS", Condition: () => Player.factions.includes("Daedalus") },
{ ID: "THE_COVENANT", Condition: () => Player.factions.includes("The Covenant") },
{ ID: "ECORP", Condition: () => Player.factions.includes("ECorp") },
{ ID: "MEGACORP", Condition: () => Player.factions.includes("MegaCorp") },
{ ID: "BACHMAN_&_ASSOCIATES", Condition: () => Player.factions.includes("Bachman & Associates") },
{ ID: "BLADE_INDUSTRIES", Condition: () => Player.factions.includes("Blade Industries") },
{ ID: "NWO", Condition: () => Player.factions.includes("NWO") },
{ ID: "CLARKE_INCORPORATED", Condition: () => Player.factions.includes("Clarke Incorporated") },
{ ID: "OMNITEK_INCORPORATED", Condition: () => Player.factions.includes("OmniTek Incorporated") },
{ ID: "FOUR_SIGMA", Condition: () => Player.factions.includes("Four Sigma") },
{ ID: "KUAIGONG_INTERNATIONAL", Condition: () => Player.factions.includes("KuaiGong International") },
{ ID: "FULCRUM_SECRET_TECHNOLOGIES", Condition: () => Player.factions.includes("Fulcrum Secret Technologies") },
{ ID: "BITRUNNERS", Condition: () => Player.factions.includes("BitRunners") },
{ ID: "THE_BLACK_HAND", Condition: () => Player.factions.includes("The Black Hand") },
{ ID: "NITESEC", Condition: () => Player.factions.includes("NiteSec") },
{ ID: "AEVUM", Condition: () => Player.factions.includes("Aevum") },
{ ID: "CHONGQING", Condition: () => Player.factions.includes("Chongqing") },
{ ID: "ISHIMA", Condition: () => Player.factions.includes("Ishima") },
{ ID: "NEW_TOKYO", Condition: () => Player.factions.includes("New Tokyo") },
{ ID: "SECTOR-12", Condition: () => Player.factions.includes("Sector-12") },
{ ID: "VOLHAVEN", Condition: () => Player.factions.includes("Volhaven") },
{ ID: "SPEAKERS_FOR_THE_DEAD", Condition: () => Player.factions.includes("Speakers for the Dead") },
{ ID: "THE_DARK_ARMY", Condition: () => Player.factions.includes("The Dark Army") },
{ ID: "THE_SYNDICATE", Condition: () => Player.factions.includes("The Syndicate") },
{ ID: "SILHOUETTE", Condition: () => Player.factions.includes("Silhouette") },
{ ID: "TETRADS", Condition: () => Player.factions.includes("Tetrads") },
{ ID: "SLUM_SNAKES", Condition: () => Player.factions.includes("Slum Snakes") },
{ ID: "NETBURNERS", Condition: () => Player.factions.includes("Netburners") },
{ ID: "TIAN_DI_HUI", Condition: () => Player.factions.includes("Tian Di Hui") },
{ ID: "CYBERSEC", Condition: () => Player.factions.includes("CyberSec") },
{ ID: "BLADEBURNERS", Condition: () => Player.factions.includes("Bladeburners") },
];
function setAchievements(achs: string[]): void {
(document as any).achievements = achs;
}
function calculateAchievements(): void {
setAchievements(achievements.filter((a) => a.Condition()).map((a) => a.ID));
}
export function initElectron(): void {
setAchievements([]);
setInterval(calculateAchievements, 5000);
}

@ -3,7 +3,8 @@ import ReactDOM from "react-dom";
import { TTheme as Theme, ThemeEvents, refreshTheme } from "./ui/React/Theme"; import { TTheme as Theme, ThemeEvents, refreshTheme } from "./ui/React/Theme";
import { LoadingScreen } from "./ui/LoadingScreen"; import { LoadingScreen } from "./ui/LoadingScreen";
import { initElectron } from "./Electron";
initElectron();
ReactDOM.render( ReactDOM.render(
<Theme> <Theme>
<LoadingScreen /> <LoadingScreen />
@ -26,7 +27,7 @@ function rerender(): void {
})(); })();
(function () { (function () {
if (process.env.NODE_ENV === "development") return; if (process.env.NODE_ENV === "development" || location.href.startsWith("file://")) return;
window.onbeforeunload = function () { window.onbeforeunload = function () {
return "Your work will be lost."; return "Your work will be lost.";
}; };

BIN
steam_api.dll Normal file

Binary file not shown.

BIN
steam_api.lib Normal file

Binary file not shown.

1
steam_appid.txt Normal file

@ -0,0 +1 @@
1812820

@ -124,6 +124,9 @@ module.exports = (env, argv) => {
isFastRefresh && new ReactRefreshWebpackPlugin(), isFastRefresh && new ReactRefreshWebpackPlugin(),
].filter(Boolean), ].filter(Boolean),
target: "web", target: "web",
// node: {
// fs: "mock",
// },
entry: entry, entry: entry,
output: { output: {
path: path.resolve(__dirname, "./"), path: path.resolve(__dirname, "./"),