From 92ad5335d65fcd9341b3d92d08467203cf7b5ab0 Mon Sep 17 00:00:00 2001 From: robofinch <86991566+robofinch@users.noreply.github.com> Date: Thu, 18 Jul 2024 13:29:01 -0500 Subject: [PATCH 01/10] ACHIEVEMENTS: Added optional NotInSteam field to Achievement interface --- src/Achievements/Achievements.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Achievements/Achievements.ts b/src/Achievements/Achievements.ts index bbf32092a..7a52b92d1 100644 --- a/src/Achievements/Achievements.ts +++ b/src/Achievements/Achievements.ts @@ -41,6 +41,7 @@ export interface Achievement { Name?: string; Description?: string; Secret?: boolean; + NotInSteam?: boolean; Condition: () => boolean; Visible?: () => boolean; AdditionalUnlock?: string[]; // IDs of achievements that should be awarded when awarding this one From 590952d3cf9b4e4515b75d82374904c57efbbd71 Mon Sep 17 00:00:00 2001 From: robofinch <86991566+robofinch@users.noreply.github.com> Date: Thu, 18 Jul 2024 13:39:25 -0500 Subject: [PATCH 02/10] ACHIEVEMENTS: Modified the achievement UI to indicate if an achievement is not on Steam --- src/Achievements/AchievementEntry.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Achievements/AchievementEntry.tsx b/src/Achievements/AchievementEntry.tsx index de6740a5b..468f02526 100644 --- a/src/Achievements/AchievementEntry.tsx +++ b/src/Achievements/AchievementEntry.tsx @@ -68,6 +68,11 @@ export function AchievementEntry({ Acquired on {achievedOn} )} + {!!achievement.NotInSteam && ( + + No equivalent Steam achievement + + )} From 65626c197a5d84a32122e8b75822b19f83b261e8 Mon Sep 17 00:00:00 2001 From: robofinch <86991566+robofinch@users.noreply.github.com> Date: Thu, 18 Jul 2024 14:06:28 -0500 Subject: [PATCH 03/10] ACHIEVEMENTS: Update achievement README and AchievementData.json header note --- src/Achievements/AchievementData.json | 3 +-- src/Achievements/README.md | 10 ++++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Achievements/AchievementData.json b/src/Achievements/AchievementData.json index 774025657..c6f737fd0 100644 --- a/src/Achievements/AchievementData.json +++ b/src/Achievements/AchievementData.json @@ -1,6 +1,5 @@ { - "note": "***** Generated from a script, overwritten by steam achievements data *****", - "fetchedOn": 1641517584274, + "note": "Originally generated by a script using Steam achievement data. Going forward, must be edited manually.", "achievements": { "CYBERSEC": { "ID": "CYBERSEC", diff --git a/src/Achievements/README.md b/src/Achievements/README.md index ed9fdcc19..865e34897 100644 --- a/src/Achievements/README.md +++ b/src/Achievements/README.md @@ -1,9 +1,11 @@ # Adding Achievements - Add a .svg in `./assets/Steam/achievements/real` -- Create the achievement in Steam Dev Portal +- If making a Steam achievement, create the achievement in Steam Dev Portal - Run `sh ./assets/Steam/achievements/pack-for-web.sh` -- Run `node ./tools/fetch-steam-achievements-data DEVKEYHERE` - - Get your key here: https://steamcommunity.com/dev/apikey +- Add an entry in `./src/Achievements/AchievementData.json` -> achievements + - It should match the information for the Steam achievement, if applicable + - Order the new achievement entry thematically - Add an entry in `./src/Achievements/Achievements.ts` -> achievements -- Commit `./dist/icons/achievements` & `./src/Achievements/AchievementData.json` + - Match the order of achievements in `AchievementData.json` +- Commit `./dist/icons/achievements` From 121fe03b588457ed93d95fd83f4a36a09c1994d6 Mon Sep 17 00:00:00 2001 From: robofinch <86991566+robofinch@users.noreply.github.com> Date: Thu, 18 Jul 2024 23:32:13 -0500 Subject: [PATCH 04/10] ACHIEVEMENTS: Changed achievement category headers The boilerplate for achievement categories was also moved to its own file. --- src/Achievements/AchievementCategory.tsx | 40 +++++++++ src/Achievements/AchievementList.tsx | 108 ++++++++--------------- 2 files changed, 79 insertions(+), 69 deletions(-) create mode 100644 src/Achievements/AchievementCategory.tsx diff --git a/src/Achievements/AchievementCategory.tsx b/src/Achievements/AchievementCategory.tsx new file mode 100644 index 000000000..88f897a5c --- /dev/null +++ b/src/Achievements/AchievementCategory.tsx @@ -0,0 +1,40 @@ +import React from "react"; + +import { Accordion, AccordionSummary, AccordionDetails, Typography } from "@mui/material"; + +import { Achievement } from "./Achievements"; + +interface IProps { + title: string; + achievements: {achievement: Achievement}[]; + allAchievements?: {achievement: Achievement}[]; + sx?: boolean; +} + +function steamCount(achievements: {achievement: Achievement}[]): number { + return achievements.filter((entry) => !entry.achievement.NotInSteam).length; +} + +export function AchievementCategory({ title, achievements, allAchievements, sx, children }: React.PropsWithChildren): JSX.Element { + // Most parts of the four categories in the old code were very similar (besides the content of + // AccordianDetails), with the Acquired category having a few differences, + // although both the Acquired and Locked categories also had an extra prop in the AccordianDetails. + return ( + + + {allAchievements ? ( + + {title} ({achievements.length}/{allAchievements.length}, {steamCount(achievements)}/{steamCount(allAchievements)} for Steam) + + ) : ( + + {title} ({achievements.length} remaining, {steamCount(achievements)} for Steam) + + )} + + + { children } + + + ); +} \ No newline at end of file diff --git a/src/Achievements/AchievementList.tsx b/src/Achievements/AchievementList.tsx index 74d574bd7..ec0d5cae5 100644 --- a/src/Achievements/AchievementList.tsx +++ b/src/Achievements/AchievementList.tsx @@ -1,7 +1,8 @@ import React from "react"; -import { Accordion, AccordionSummary, AccordionDetails, Box, Typography } from "@mui/material"; +import { Box, Typography } from "@mui/material"; +import { AchievementCategory } from "./AchievementCategory"; import { AchievementEntry } from "./AchievementEntry"; import { Achievement, PlayerAchievement } from "./Achievements"; import { Settings } from "../Settings/Settings"; @@ -52,81 +53,50 @@ export function AchievementList({ achievements, playerAchievements }: IProps): J }} > {unlocked.length > 0 && ( - - - - Acquired ({unlocked.length}/{data.length}) - - - - {unlocked.map((item) => ( - - ))} - - + + {unlocked.map((item) => ( + + ))} + )} - {locked.length > 0 && ( - - - - Locked ({locked.length} remaining) - - - - {locked.map((item) => ( - - ))} - - + + {locked.map((item) => ( + + ))} + )} - {unavailable.length > 0 && ( - - - - Unavailable ({unavailable.length} remaining) - - - - - {unavailable.length} additional achievements hidden behind content you don't have access to. - - - + + + {unavailable.length} additional achievements hidden behind content you don't have access to. + + )} - {secret.length > 0 && ( - - - - Secret ({secret.length} remaining) - - - - - {secret.map((item) => ( - - -
-
- ))} -
-
-
+ + + {secret.map((item) => ( + + +
+
+ ))} +
+
)} ); -} +} \ No newline at end of file From dbdbc8d76c32e647b99e1c252786a194ded129b4 Mon Sep 17 00:00:00 2001 From: robofinch <86991566+robofinch@users.noreply.github.com> Date: Thu, 18 Jul 2024 23:36:31 -0500 Subject: [PATCH 05/10] ACHIEVEMENTS: Minor adjustment to AchievementEntry Added a LinkOff icon and fixed coloring for AchievementEntries --- src/Achievements/AchievementEntry.tsx | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/Achievements/AchievementEntry.tsx b/src/Achievements/AchievementEntry.tsx index 468f02526..3331744ee 100644 --- a/src/Achievements/AchievementEntry.tsx +++ b/src/Achievements/AchievementEntry.tsx @@ -1,6 +1,7 @@ import React from "react"; import { Box, Typography } from "@mui/material"; +import LinkOffIcon from "@mui/icons-material/LinkOff"; import { Achievement } from "./Achievements"; import { Settings } from "../Settings/Settings"; @@ -23,6 +24,7 @@ export function AchievementEntry({ const isUnlocked = !!unlockedOn; const mainColor = isUnlocked ? Settings.theme.primary : Settings.theme.secondarylight; + const captionColor = isUnlocked ? Settings.theme.primarydark : Settings.theme.secondary; let achievedOn = ""; if (unlockedOn) { @@ -64,14 +66,24 @@ export function AchievementEntry({ {achievement.Description} {isUnlocked && ( - + Acquired on {achievedOn} )} {!!achievement.NotInSteam && ( - - No equivalent Steam achievement - + + + + No equivalent Steam achievement + + )} From ea25b24ebb879e35f89657b1425b0e9336564b94 Mon Sep 17 00:00:00 2001 From: robofinch <86991566+robofinch@users.noreply.github.com> Date: Thu, 18 Jul 2024 23:38:46 -0500 Subject: [PATCH 06/10] ACHIEVEMENTS: Add description to achievement page Alignment now also matches Milestones page --- src/Achievements/AchievementsRoot.tsx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Achievements/AchievementsRoot.tsx b/src/Achievements/AchievementsRoot.tsx index 0e7eb3b11..f617c4e28 100644 --- a/src/Achievements/AchievementsRoot.tsx +++ b/src/Achievements/AchievementsRoot.tsx @@ -3,14 +3,13 @@ import React from "react"; import { Theme } from "@mui/material/styles"; import { AchievementList } from "./AchievementList"; import { achievements } from "./Achievements"; -import { Typography } from "@mui/material"; +import { Box, Typography } from "@mui/material"; import { Player } from "@player"; import { makeStyles } from "tss-react/mui"; const useStyles = makeStyles()((theme: Theme) => ({ root: { width: 50, - padding: theme.spacing(2), userSelect: "none", }, })); @@ -20,7 +19,13 @@ export function AchievementsRoot(): JSX.Element { return (
Achievements - + + + Achievements are a persistent reward for completing challenges. A limited number of Bitburner achievements + have corresponding achievements in Steam. + + +
); } From db1f31962d555d38dd682e0920962d5bfefe46f0 Mon Sep 17 00:00:00 2001 From: robofinch <86991566+robofinch@users.noreply.github.com> Date: Fri, 19 Jul 2024 12:37:35 -0500 Subject: [PATCH 07/10] ACHIEVEMENTS: Add link icons in top right Also minor formatting changes --- src/Achievements/AchievementCategory.tsx | 23 +++--- src/Achievements/AchievementEntry.tsx | 96 +++++++++++++++--------- src/Achievements/AchievementList.tsx | 2 +- src/Achievements/AchievementsRoot.tsx | 9 +-- 4 files changed, 80 insertions(+), 50 deletions(-) diff --git a/src/Achievements/AchievementCategory.tsx b/src/Achievements/AchievementCategory.tsx index 88f897a5c..6492393f1 100644 --- a/src/Achievements/AchievementCategory.tsx +++ b/src/Achievements/AchievementCategory.tsx @@ -6,16 +6,22 @@ import { Achievement } from "./Achievements"; interface IProps { title: string; - achievements: {achievement: Achievement}[]; - allAchievements?: {achievement: Achievement}[]; + achievements: { achievement: Achievement }[]; + allAchievements?: { achievement: Achievement }[]; sx?: boolean; } -function steamCount(achievements: {achievement: Achievement}[]): number { +function steamCount(achievements: { achievement: Achievement }[]): number { return achievements.filter((entry) => !entry.achievement.NotInSteam).length; } -export function AchievementCategory({ title, achievements, allAchievements, sx, children }: React.PropsWithChildren): JSX.Element { +export function AchievementCategory({ + title, + achievements, + allAchievements, + sx, + children, +}: React.PropsWithChildren): JSX.Element { // Most parts of the four categories in the old code were very similar (besides the content of // AccordianDetails), with the Acquired category having a few differences, // although both the Acquired and Locked categories also had an extra prop in the AccordianDetails. @@ -24,7 +30,8 @@ export function AchievementCategory({ title, achievements, allAchievements, sx, {allAchievements ? ( - {title} ({achievements.length}/{allAchievements.length}, {steamCount(achievements)}/{steamCount(allAchievements)} for Steam) + {title} ({achievements.length}/{allAchievements.length}, {steamCount(achievements)}/ + {steamCount(allAchievements)} for Steam) ) : ( @@ -32,9 +39,7 @@ export function AchievementCategory({ title, achievements, allAchievements, sx, )} - - { children } - + {children} ); -} \ No newline at end of file +} diff --git a/src/Achievements/AchievementEntry.tsx b/src/Achievements/AchievementEntry.tsx index 3331744ee..5c627d5d2 100644 --- a/src/Achievements/AchievementEntry.tsx +++ b/src/Achievements/AchievementEntry.tsx @@ -1,6 +1,7 @@ import React from "react"; -import { Box, Typography } from "@mui/material"; +import { Box, Tooltip, Typography } from "@mui/material"; +import LinkIcon from "@mui/icons-material/Link"; import LinkOffIcon from "@mui/icons-material/LinkOff"; import { Achievement } from "./Achievements"; @@ -25,6 +26,7 @@ export function AchievementEntry({ const mainColor = isUnlocked ? Settings.theme.primary : Settings.theme.secondarylight; const captionColor = isUnlocked ? Settings.theme.primarydark : Settings.theme.secondary; + const iconColor = isUnlocked ? Settings.theme.primary : Settings.theme.primarydark; let achievedOn = ""; if (unlockedOn) { @@ -38,54 +40,78 @@ export function AchievementEntry({ mb: 2, }} > - - - - {achievement.Name} - - - {achievement.Description} - - {isUnlocked && ( - - Acquired on {achievedOn} + + + + {achievement.Name} - )} - {!!achievement.NotInSteam && ( - - + + {achievement.Description} + + {isUnlocked && ( - No equivalent Steam achievement + Acquired on {achievedOn} - - )} + )} + {achievement.NotInSteam && ( + + + + No equivalent Steam achievement + + + )} + + + + {achievement.NotInSteam ? "No equivalent Steam achievement" : "Has a Steam achievement"} +
+ } + > + + {achievement.NotInSteam ? ( + + ) : ( + + )} + + ); diff --git a/src/Achievements/AchievementList.tsx b/src/Achievements/AchievementList.tsx index ec0d5cae5..53bc1ce6f 100644 --- a/src/Achievements/AchievementList.tsx +++ b/src/Achievements/AchievementList.tsx @@ -99,4 +99,4 @@ export function AchievementList({ achievements, playerAchievements }: IProps): J ); -} \ No newline at end of file +} diff --git a/src/Achievements/AchievementsRoot.tsx b/src/Achievements/AchievementsRoot.tsx index f617c4e28..2656ab97d 100644 --- a/src/Achievements/AchievementsRoot.tsx +++ b/src/Achievements/AchievementsRoot.tsx @@ -1,18 +1,17 @@ import React from "react"; -import { Theme } from "@mui/material/styles"; import { AchievementList } from "./AchievementList"; import { achievements } from "./Achievements"; import { Box, Typography } from "@mui/material"; import { Player } from "@player"; import { makeStyles } from "tss-react/mui"; -const useStyles = makeStyles()((theme: Theme) => ({ +const useStyles = makeStyles()({ root: { width: 50, userSelect: "none", }, -})); +}); export function AchievementsRoot(): JSX.Element { const { classes } = useStyles(); @@ -21,8 +20,8 @@ export function AchievementsRoot(): JSX.Element { Achievements - Achievements are a persistent reward for completing challenges. A limited number of Bitburner achievements - have corresponding achievements in Steam. + Achievements are persistent rewards for various actions and challenges. A limited number of Bitburner + achievements have corresponding achievements in Steam. From 1970d3e48ab4fa42c68766685ec8c71ac7748ea5 Mon Sep 17 00:00:00 2001 From: robofinch <86991566+robofinch@users.noreply.github.com> Date: Fri, 19 Jul 2024 19:47:11 -0500 Subject: [PATCH 08/10] ACHIEVEMENTS: tweak icon coloring --- src/Achievements/AchievementCategory.tsx | 3 ++- src/Achievements/AchievementEntry.tsx | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Achievements/AchievementCategory.tsx b/src/Achievements/AchievementCategory.tsx index 6492393f1..616310a9b 100644 --- a/src/Achievements/AchievementCategory.tsx +++ b/src/Achievements/AchievementCategory.tsx @@ -25,8 +25,9 @@ export function AchievementCategory({ // Most parts of the four categories in the old code were very similar (besides the content of // AccordianDetails), with the Acquired category having a few differences, // although both the Acquired and Locked categories also had an extra prop in the AccordianDetails. + // The 264px minWidth feels scuffed, but fixes an edge case. return ( - + {allAchievements ? ( diff --git a/src/Achievements/AchievementEntry.tsx b/src/Achievements/AchievementEntry.tsx index 5c627d5d2..f6e60e713 100644 --- a/src/Achievements/AchievementEntry.tsx +++ b/src/Achievements/AchievementEntry.tsx @@ -88,7 +88,7 @@ export function AchievementEntry({ alignItems: "center", }} > - + No equivalent Steam achievement @@ -104,7 +104,7 @@ export function AchievementEntry({ } > - + {achievement.NotInSteam ? ( ) : ( From 59e2783f7876fb57a73cd911bbb5e736686b0c6f Mon Sep 17 00:00:00 2001 From: robofinch <86991566+robofinch@users.noreply.github.com> Date: Fri, 19 Jul 2024 20:03:43 -0500 Subject: [PATCH 09/10] ACHIEVEMENTS: Remove top-right link icon --- src/Achievements/AchievementEntry.tsx | 96 ++++++++++----------------- 1 file changed, 35 insertions(+), 61 deletions(-) diff --git a/src/Achievements/AchievementEntry.tsx b/src/Achievements/AchievementEntry.tsx index f6e60e713..45c9028e1 100644 --- a/src/Achievements/AchievementEntry.tsx +++ b/src/Achievements/AchievementEntry.tsx @@ -1,7 +1,6 @@ import React from "react"; -import { Box, Tooltip, Typography } from "@mui/material"; -import LinkIcon from "@mui/icons-material/Link"; +import { Box, Typography } from "@mui/material"; import LinkOffIcon from "@mui/icons-material/LinkOff"; import { Achievement } from "./Achievements"; @@ -26,7 +25,6 @@ export function AchievementEntry({ const mainColor = isUnlocked ? Settings.theme.primary : Settings.theme.secondarylight; const captionColor = isUnlocked ? Settings.theme.primarydark : Settings.theme.secondary; - const iconColor = isUnlocked ? Settings.theme.primary : Settings.theme.primarydark; let achievedOn = ""; if (unlockedOn) { @@ -40,78 +38,54 @@ export function AchievementEntry({ mb: 2, }} > - + - - - - {achievement.Name} + + {achievement.Name} + + + {achievement.Description} + + {isUnlocked && ( + + Acquired on {achievedOn} - - {achievement.Description} - - {isUnlocked && ( + )} + {achievement.NotInSteam && ( + + - Acquired on {achievedOn} + No equivalent Steam achievement - )} - {achievement.NotInSteam && ( - - - - No equivalent Steam achievement - - - )} - + + )} - - - {achievement.NotInSteam ? "No equivalent Steam achievement" : "Has a Steam achievement"} - - } - > - - {achievement.NotInSteam ? ( - - ) : ( - - )} - - ); From 562479c5cc117709126b7c01e04ecfb6d2545cb7 Mon Sep 17 00:00:00 2001 From: robofinch <86991566+robofinch@users.noreply.github.com> Date: Sat, 20 Jul 2024 13:00:42 -0500 Subject: [PATCH 10/10] ACHIEVEMENTS: Script to recolor SVGs on MacOS --- assets/Steam/achievements/pack-for-web-mac.sh | 16 ++++++++++++++++ src/Achievements/README.md | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 assets/Steam/achievements/pack-for-web-mac.sh diff --git a/assets/Steam/achievements/pack-for-web-mac.sh b/assets/Steam/achievements/pack-for-web-mac.sh new file mode 100644 index 000000000..dcff074b6 --- /dev/null +++ b/assets/Steam/achievements/pack-for-web-mac.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +BASEDIR=$(dirname "$0") +ROOTDIR=$BASEDIR/../../.. +echo $ROOTDIR +rm -rf $ROOTDIR/dist/icons/achievements +mkdir -p $ROOTDIR/dist/icons +cp -r $BASEDIR/real $ROOTDIR/dist/icons/achievements +for i in $ROOTDIR/dist/icons/achievements/*.svg; do + echo $i + # Make background transparent and replace green with black + # The icons will be recolored by css filters matching the player's theme + # MacOS uses FreeBSD-style sed instead of GNU sed + sed -i '' "s/fill:#000000;/fill-opacity: 0%;/g" "$i" + sed -i '' "s/fill:#00ff00;/fill:#000000;/g" "$i" +done diff --git a/src/Achievements/README.md b/src/Achievements/README.md index 865e34897..c6df7d974 100644 --- a/src/Achievements/README.md +++ b/src/Achievements/README.md @@ -2,7 +2,7 @@ - Add a .svg in `./assets/Steam/achievements/real` - If making a Steam achievement, create the achievement in Steam Dev Portal -- Run `sh ./assets/Steam/achievements/pack-for-web.sh` +- Run `sh ./assets/Steam/achievements/pack-for-web.sh`, or `pack-for-web-mac.sh` for MacOS - Add an entry in `./src/Achievements/AchievementData.json` -> achievements - It should match the information for the Steam achievement, if applicable - Order the new achievement entry thematically