ps99-api 2.4.0 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/.github/workflows/release-on-main.yml +1 -2
  2. package/.idea/runConfigurations/test_changing.xml +1 -1
  3. package/debug_currency.json +57 -0
  4. package/debug_goals.json +271 -0
  5. package/dist/ps99-api.d.ts +2 -0
  6. package/dist/ps99-api.js +4 -1
  7. package/dist/ps99-api.js.map +1 -1
  8. package/dist/request-client/axios.js +6 -1
  9. package/dist/request-client/axios.js.map +1 -1
  10. package/dist/responses/collection/index.d.ts +1 -0
  11. package/dist/responses/collection/index.js +15 -0
  12. package/dist/responses/collection/index.js.map +1 -1
  13. package/dist/responses/collection/rarity.d.ts +1 -0
  14. package/example-web/react/package-lock.json +1504 -1470
  15. package/example-web/react2/package-lock.json +3089 -2766
  16. package/example-web/react2/package.json +6 -1
  17. package/example-web/react2/public/assets/gold_variant_icon.png +0 -0
  18. package/example-web/react2/public/assets/hot_cocoa_egg.png +0 -0
  19. package/example-web/react2/public/index.html +34 -31
  20. package/example-web/react2/src/App.tsx +15 -15
  21. package/example-web/react2/src/assets/guild_placeholder.png +0 -0
  22. package/example-web/react2/src/components/AchievementsComponent.tsx +74 -19
  23. package/example-web/react2/src/components/AutoSizer.tsx +49 -0
  24. package/example-web/react2/src/components/BoostsComponent.tsx +16 -5
  25. package/example-web/react2/src/components/BoothsComponent.tsx +22 -52
  26. package/example-web/react2/src/components/BoxesComponent.tsx +48 -16
  27. package/example-web/react2/src/components/BuffsComponent.tsx +82 -34
  28. package/example-web/react2/src/components/CharmsComponent.tsx +84 -24
  29. package/example-web/react2/src/components/CollectionConfigIndex.tsx +867 -33
  30. package/example-web/react2/src/components/CollectionsIndex.tsx +380 -27
  31. package/example-web/react2/src/components/CollectionsLayout.tsx +60 -0
  32. package/example-web/react2/src/components/CurrencyComponent.tsx +57 -39
  33. package/example-web/react2/src/components/DynamicCollectionConfigData.tsx +172 -15
  34. package/example-web/react2/src/components/EggsComponent.tsx +50 -12
  35. package/example-web/react2/src/components/EnchantsComponent.tsx +88 -42
  36. package/example-web/react2/src/components/FishingRodsComponent.tsx +36 -22
  37. package/example-web/react2/src/components/Footer.tsx +18 -8
  38. package/example-web/react2/src/components/FruitsComponent.tsx +40 -17
  39. package/example-web/react2/src/components/GenericFetchComponent.tsx +9 -1
  40. package/example-web/react2/src/components/GuildBattlesComponent.tsx +41 -34
  41. package/example-web/react2/src/components/Header.tsx +39 -52
  42. package/example-web/react2/src/components/HomePage.tsx +15 -17
  43. package/example-web/react2/src/components/HoverboardsComponent.tsx +23 -99
  44. package/example-web/react2/src/components/ImageComponent.tsx +255 -45
  45. package/example-web/react2/src/components/ItemCard.tsx +240 -0
  46. package/example-web/react2/src/components/LootboxesComponent.tsx +22 -7
  47. package/example-web/react2/src/components/MasteryComponent.tsx +165 -30
  48. package/example-web/react2/src/components/MerchantsComponent.tsx +41 -16
  49. package/example-web/react2/src/components/MiscItemsComponent.tsx +26 -31
  50. package/example-web/react2/src/components/PetsComponent.tsx +100 -61
  51. package/example-web/react2/src/components/PotionsComponent.tsx +121 -27
  52. package/example-web/react2/src/components/RandomEventsComponent.tsx +32 -23
  53. package/example-web/react2/src/components/RanksComponent.tsx +187 -62
  54. package/example-web/react2/src/components/RarityComponent.tsx +123 -5
  55. package/example-web/react2/src/components/ReactWindowMock.tsx +73 -0
  56. package/example-web/react2/src/components/RebirthsComponent.tsx +36 -19
  57. package/example-web/react2/src/components/SecretRoomsComponent.tsx +5 -4
  58. package/example-web/react2/src/components/SeedsComponent.tsx +41 -21
  59. package/example-web/react2/src/components/ShovelsComponent.tsx +21 -9
  60. package/example-web/react2/src/components/Sidebar.tsx +105 -0
  61. package/example-web/react2/src/components/SprinklersComponent.tsx +25 -10
  62. package/example-web/react2/src/components/Tooltip.tsx +36 -0
  63. package/example-web/react2/src/components/UltimatesComponent.tsx +28 -16
  64. package/example-web/react2/src/components/UpgradesComponent.tsx +97 -47
  65. package/example-web/react2/src/components/WateringCansComponent.tsx +20 -14
  66. package/example-web/react2/src/components/WorldsComponent.tsx +21 -11
  67. package/example-web/react2/src/components/XPPotionsComponent.tsx +28 -11
  68. package/example-web/react2/src/components/ZoneFlagsComponent.tsx +25 -14
  69. package/example-web/react2/src/components/ZonesComponent.tsx +43 -60
  70. package/example-web/react2/src/constants/collectionIcons.ts +29 -0
  71. package/example-web/react2/src/context/CollectionDataContext.tsx +62 -0
  72. package/example-web/react2/src/context/ScrollContext.tsx +35 -0
  73. package/example-web/react2/src/hooks/useCollapsibleHeader.ts +69 -0
  74. package/example-web/react2/src/hooks/useExpandableList.ts +38 -0
  75. package/example-web/react2/src/hooks/useItemResolution.ts +351 -0
  76. package/example-web/react2/src/index.css +257 -0
  77. package/example-web/react2/src/index.tsx +2 -1
  78. package/example-web/react2/src/utils/gigantix.ts +40 -0
  79. package/example-web/react2/temp_model.rbxm +0 -0
  80. package/example-web/react2/webpack.config.js +103 -47
  81. package/package.json +11 -11
  82. package/ranks.json +1 -0
  83. package/repro_collection_fetch.ts +33 -0
  84. package/repro_image_fetch.ts +50 -0
  85. package/src/__tests__/__snapshots__/ps99-api-changes.ts.snap +34841 -10439
  86. package/src/__tests__/__snapshots__/ps99-api-live.ts.snap +160667 -67217
  87. package/src/ps99-api.ts +9 -5
  88. package/src/request-client/axios.ts +6 -2
  89. package/src/responses/collection/index.ts +1 -0
  90. package/src/responses/collection/rarity.ts +1 -0
  91. package/tsconfig.json +1 -1
  92. package/example-web/react2/public/service-worker.js +0 -63
@@ -1,53 +1,60 @@
1
1
  import React from "react";
2
2
  import { CollectionConfigData, GuildBattlePlacementReward, GuildBattleRewardItem } from "ps99-api";
3
3
  import DynamicCollectionConfigData from "./DynamicCollectionConfigData";
4
- import PetsComponent from "./PetsComponent";
4
+ import { useItemResolution } from "../hooks/useItemResolution";
5
+ import ItemCard from "./ItemCard";
6
+ import ImageComponent from "./ImageComponent";
7
+ // @ts-ignore
8
+ import placeholderIcon from "../assets/guild_placeholder.png";
5
9
 
6
10
  const rewardTypes = ["Clan Gift", "Booth", "Hoverboard", "Pet"];
7
11
 
8
12
  const GuildBattlesComponent: React.FC<{
9
13
  configData: CollectionConfigData<"GuildBattles">;
10
14
  }> = ({ configData }) => {
11
- const renderRewardComponent = (reward: GuildBattlePlacementReward | GuildBattleRewardItem, index: number) => {
12
- const rewardType = rewardTypes[index % rewardTypes.length];
15
+ const { resolveItem, getRarityColor, loading } = useItemResolution();
13
16
 
17
+ if (loading) return <div>Loading data...</div>;
18
+
19
+ const renderRewardItem = (reward: GuildBattlePlacementReward | GuildBattleRewardItem, index: number) => {
14
20
  let id: string;
21
+ let amount = 1; // Default amount
15
22
  let pt: number | undefined;
16
23
 
17
24
  if ("Item" in reward) { // GuildBattlePlacementReward
18
25
  id = reward.Item._data.id;
19
26
  pt = reward.Item._data.pt;
27
+ amount = (reward.Item._data as any)._am || 1;
20
28
  } else { // GuildBattleRewardItem
21
29
  id = reward._data.id;
30
+ amount = (reward._data as any)._am || 1;
22
31
  }
23
32
 
24
- if (id.startsWith("Huge")) {
25
- return (
26
- <DynamicCollectionConfigData
27
- collectionName="Pets"
28
- configName={id}
29
- render={(configData: CollectionConfigData<"Pets">) => <PetsComponent configData={configData} displayType="specific" pt={pt} />}
30
- />
31
- );
32
- } else if (id.startsWith("Exclusive Egg")) {
33
- return <DynamicCollectionConfigData collectionName="Eggs" configName={id} />;
34
- }
33
+ // Try to resolve the item using the hook
34
+ const itemData = resolveItem(id, pt);
35
+ const rarityColor = itemData?.rarity ? getRarityColor(itemData.rarity) : null;
35
36
 
36
- switch (rewardType) {
37
- case "Clan Gift":
38
- return <DynamicCollectionConfigData collectionName="Lootboxes" configName="Clan Gift" />;
39
- case "Booth":
40
- return <DynamicCollectionConfigData collectionName="Booths" configName={`Booth | ${id}`} />;
41
- case "Hoverboard":
42
- return <DynamicCollectionConfigData collectionName="Hoverboards" configName={`Hoverboard | ${id}`} />;
43
- default:
44
- return <p><strong>Item ID:</strong> {id}</p>;
45
- }
37
+ return (
38
+ <ItemCard
39
+ key={index}
40
+ id={id}
41
+ amount={amount}
42
+ label={id}
43
+ tn={pt}
44
+ itemData={itemData}
45
+ rarityColor={rarityColor}
46
+ />
47
+ );
46
48
  };
47
49
 
48
50
  return (
49
51
  <div style={{ padding: "1em", border: "1px solid #ccc", borderRadius: "8px", marginBottom: "2em" }}>
50
- <h2 style={{ borderBottom: "2px solid #ccc", paddingBottom: "0.5em" }}>{configData.Title}</h2>
52
+ <div style={{ display: "flex", alignItems: "center", gap: "1em", borderBottom: "2px solid #ccc", paddingBottom: "0.5em" }}>
53
+ <div style={{ width: "64px", height: "64px" }}>
54
+ <ImageComponent src={(configData as any).Icon || placeholderIcon} alt={configData.Title} />
55
+ </div>
56
+ <h2 style={{ margin: 0 }}>{configData.Title}</h2>
57
+ </div>
51
58
  <p><strong>Start Time:</strong> {new Date(configData.StartTime * 1000).toLocaleString()}</p>
52
59
  <p><strong>Finish Time:</strong> {new Date(configData.FinishTime * 1000).toLocaleString()}</p>
53
60
  {configData.HasGoals && <p><strong>Has Goals:</strong> Yes</p>}
@@ -56,15 +63,15 @@ const GuildBattlesComponent: React.FC<{
56
63
  <div style={{ display: 'flex', flexWrap: 'wrap', gap: '1em' }}>
57
64
  {configData.PlacementRewards?.map((reward, index) => (
58
65
  <div key={index} style={{
59
- border: '1px solid #ccc',
60
- borderRadius: '8px',
61
- padding: '1em',
62
- flex: '1 1 calc(33% - 1em)',
63
- boxSizing: 'border-box',
66
+ flex: '1 1 300px', // Allow flex but with base width
67
+ maxWidth: '350px',
68
+ margin: '0 auto'
64
69
  }}>
65
- {renderRewardComponent(reward, index)}
66
- <p><strong>Best:</strong> {reward.Best}</p>
67
- <p><strong>Worst:</strong> {reward.Worst}</p>
70
+ {renderRewardItem(reward, index)}
71
+ <div style={{ textAlign: 'center', marginTop: '10px', fontSize: '0.9em', color: '#666' }}>
72
+ <p style={{ margin: '2px 0' }}><strong>Best:</strong> {reward.Best}</p>
73
+ <p style={{ margin: '2px 0' }}><strong>Worst:</strong> {reward.Worst}</p>
74
+ </div>
68
75
  </div>
69
76
  ))}
70
77
  </div>
@@ -83,7 +90,7 @@ const GuildBattlesComponent: React.FC<{
83
90
  flex: '1 1 calc(33% - 1em)',
84
91
  boxSizing: 'border-box',
85
92
  }}>
86
- {renderRewardComponent(reward, index)}
93
+ {renderRewardItem(reward, index)}
87
94
  </div>
88
95
  ))}
89
96
  </div>
@@ -5,61 +5,48 @@ const Header: React.FC = () => {
5
5
  const location = useLocation();
6
6
  const pathnames = location.pathname.split("/").filter((x) => x);
7
7
 
8
+ const isCollectionsRoute = location.pathname.startsWith("/collections");
9
+ const [isMobile, setIsMobile] = React.useState(window.innerWidth < 768);
10
+
11
+ React.useEffect(() => {
12
+ const handleResize = () => setIsMobile(window.innerWidth < 768);
13
+ window.addEventListener("resize", handleResize);
14
+ return () => window.removeEventListener("resize", handleResize);
15
+ }, []);
16
+
17
+
18
+
19
+ if (isMobile && isCollectionsRoute) {
20
+ return null;
21
+ }
22
+
8
23
  return (
9
- <nav
10
- style={{
11
- padding: "1em",
12
- background: "#f8f9fa",
13
- borderBottom: "1px solid #e7e7e7",
14
- display: "flex",
15
- justifyContent: "space-between",
16
- alignItems: "center",
17
- }}
18
- >
19
- <div style={{ display: "flex", alignItems: "center" }}>
20
- <Link
21
- to="/"
22
- style={{
23
- textDecoration: "none",
24
- color: "#007bff",
25
- display: "flex",
26
- alignItems: "center",
27
- }}
28
- >
29
- <img
30
- src="/node-ps99-api/icons/icon-192x192.png"
31
- alt="Home"
32
- style={{ width: "40px", height: "40px", marginRight: "0.5em" }}
33
- />
34
- </Link>
35
- <ol
36
- style={{ display: "flex", listStyle: "none", padding: 0, margin: 0 }}
37
- >
38
- <li style={{ margin: "0 0.5em" }}>
39
- <Link to="/" style={{ textDecoration: "none", color: "#007bff" }}>
40
- Home
24
+ <nav className="game-header" style={{ flexWrap: 'wrap', justifyContent: 'center' }}>
25
+ <div style={{ display: "flex", alignItems: "center", width: '100%', justifyContent: 'space-between' }}>
26
+ <div style={{ display: "flex", alignItems: "center" }}>
27
+ <Link
28
+ to="/"
29
+ style={{
30
+ textDecoration: "none",
31
+ display: "flex",
32
+ alignItems: "center",
33
+ }}
34
+ >
35
+ <img
36
+ src="/node-ps99-api/icons/icon-192x192.png"
37
+ alt="Home"
38
+ style={{ width: "40px", height: "40px", marginRight: "0.5em", border: "2px solid white", borderRadius: "50%" }}
39
+ />
40
+ </Link>
41
+ <h1 style={{ margin: 0, fontSize: '1.5rem', color: 'white', lineHeight: 1 }}>
42
+ <Link to="/">
43
+ Pet Simulator 99
41
44
  </Link>
42
- </li>
43
- {pathnames.map((value, index) => {
44
- const to = `/${pathnames.slice(0, index + 1).join("/")}`;
45
- return (
46
- <li key={to} style={{ margin: "0 0.5em" }}>
47
- <Link
48
- to={to}
49
- style={{ textDecoration: "none", color: "#007bff" }}
50
- >
51
- {decodeURIComponent(value)}
52
- </Link>
53
- </li>
54
- );
55
- })}
56
- </ol>
45
+ </h1>
46
+ </div>
47
+
48
+ {/* Placeholder for potential mobile menu burger if needed later */}
57
49
  </div>
58
- <h1 style={{ margin: 0 }}>
59
- <Link to="/" style={{ textDecoration: "none", color: "#007bff" }}>
60
- Pet Simulator 99 API
61
- </Link>
62
- </h1>
63
50
  </nav>
64
51
  );
65
52
  };
@@ -3,24 +3,22 @@ import { Link } from "react-router-dom";
3
3
 
4
4
  const HomePage: React.FC = () => {
5
5
  return (
6
- <div style={{ textAlign: "center", padding: "2em" }}>
7
- <h1>Welcome to Pet Simulator 99 API</h1>
8
- <p>
9
- Your one-stop solution for accessing all Pet Simulator 99 configData.
6
+ <div style={{ textAlign: "center", padding: "4em", marginTop: "50px" }}>
7
+ <h1 style={{ fontSize: "3rem", marginBottom: "0.5em", color: "var(--primary-color)", textShadow: "4px 4px 0px var(--border-color)" }}>
8
+ Pet Simulator 99
9
+ </h1>
10
+ <p style={{ fontSize: "1.2rem", marginBottom: "2em" }}>
11
+ Explore the world of Pet Simulator 99! Check out all the items, pets, and collections.
10
12
  </p>
11
- <p>Select a collection to get started:</p>
12
- <Link
13
- to="/collections"
14
- style={{
15
- padding: "0.5em 1em",
16
- background: "#007bff",
17
- color: "#fff",
18
- textDecoration: "none",
19
- borderRadius: "4px",
20
- }}
21
- >
22
- View Collections
23
- </Link>
13
+
14
+ <div style={{ display: "flex", justifyContent: "center", gap: "20px" }}>
15
+ <Link
16
+ to="/collections"
17
+ className="game-button"
18
+ >
19
+ Collections
20
+ </Link>
21
+ </div>
24
22
  </div>
25
23
  );
26
24
  };
@@ -1,109 +1,33 @@
1
1
  import React from "react";
2
2
  import { CollectionConfigData } from "ps99-api";
3
- import ImageComponent from "./ImageComponent";
3
+ import ItemCard from "./ItemCard";
4
+ import { useItemResolution } from "../hooks/useItemResolution";
4
5
 
5
6
  const HoverboardsComponent: React.FC<{
6
7
  configData: CollectionConfigData<"Hoverboards">;
7
8
  }> = ({ configData }) => {
9
+ const { getRarityColor } = useItemResolution();
10
+ const rarityColor = configData.Rarity ? getRarityColor(configData.Rarity) : null;
11
+
8
12
  return (
9
- <div
10
- style={{
11
- padding: "1em",
12
- border: "1px solid #ccc",
13
- borderRadius: "8px",
14
- backgroundColor: "#f9f9f9",
15
- }}
16
- >
17
- <h2 style={{ borderBottom: "2px solid #ccc", paddingBottom: "0.5em" }}>
18
- {configData.DisplayName}
19
- </h2>
20
- <ImageComponent src={configData.Icon} alt={configData.DisplayName} />
21
- <p>
22
- <strong>Description:</strong> {configData.Desc}
23
- </p>
24
- <p>
25
- <strong>Rarity:</strong> {configData.Rarity.DisplayName}
26
- </p>
27
- <p>
28
- <strong>Rarity Number:</strong> {configData.Rarity.RarityNumber}
29
- </p>
30
- {configData.Tradable && (
31
- <p>
32
- <strong>Tradable:</strong> Yes
33
- </p>
34
- )}
35
- {configData.CanBeShiny && (
36
- <p>
37
- <strong>Can Be Shiny:</strong> Yes
38
- </p>
39
- )}
40
- {configData.HoverHeight && (
41
- <p>
42
- <strong>Hover Height:</strong> {configData.HoverHeight}
43
- </p>
44
- )}
45
- {configData.RotationLimit && (
46
- <p>
47
- <strong>Rotation Limit:</strong> {configData.RotationLimit}
48
- </p>
49
- )}
50
- {configData.ProductId && (
51
- <p>
52
- <strong>Product ID:</strong> {configData.ProductId}
53
- </p>
54
- )}
55
- {configData.Animation && (
56
- <p>
57
- <strong>Animation:</strong> {configData.Animation}
58
- </p>
59
- )}
60
- {configData.BobRate && (
61
- <p>
62
- <strong>Bob Rate:</strong> {configData.BobRate}
63
- </p>
64
- )}
65
- {configData.PitchScale && (
66
- <p>
67
- <strong>Pitch Scale:</strong> {configData.PitchScale}
68
- </p>
69
- )}
70
- {configData.MaxRoll && (
71
- <p>
72
- <strong>Max Roll:</strong> {configData.MaxRoll}
73
- </p>
74
- )}
75
- {configData.DefaultJumpSpeedBoost && (
76
- <p>
77
- <strong>Default Jump Speed Boost:</strong>{" "}
78
- {configData.DefaultJumpSpeedBoost}
79
- </p>
80
- )}
81
- {configData.IdleVolumeSpeedScale && (
82
- <p>
83
- <strong>Idle Volume Speed Scale:</strong>{" "}
84
- {configData.IdleVolumeSpeedScale}
85
- </p>
86
- )}
87
- {configData.IdlePitchScale && (
88
- <p>
89
- <strong>Idle Pitch Scale:</strong> {configData.IdlePitchScale}
90
- </p>
91
- )}
92
- {configData.BlockcastScale && (
93
- <p>
94
- <strong>Blockcast Scale:</strong> {configData.BlockcastScale}
95
- </p>
96
- )}
97
- {configData.SkateMode && (
98
- <p>
99
- <strong>Skate Mode:</strong> Yes
100
- </p>
101
- )}
102
- {configData.IdleVolume && (
103
- <p>
104
- <strong>Idle Volume:</strong> {configData.IdleVolume}
105
- </p>
106
- )}
13
+ <div style={{ width: '100%', height: '100%', boxSizing: 'border-box' }}>
14
+ <ItemCard
15
+ id={configData.DisplayName}
16
+ amount={1}
17
+ label={configData.DisplayName}
18
+ itemData={{
19
+ icon: configData.Icon,
20
+ rarity: configData.Rarity,
21
+ name: configData.DisplayName
22
+ }}
23
+ rarityColor={rarityColor}
24
+ />
25
+ <div style={{ marginTop: '10px', fontSize: '0.9em', color: '#666', textAlign: 'center' }}>
26
+ <p>{configData.Desc}</p>
27
+ {configData.ProductId && <p>ID: {configData.ProductId}</p>}
28
+ {configData.HoverHeight && <p>Height: {configData.HoverHeight}</p>}
29
+ <p>Speed: {configData.DefaultJumpSpeedBoost || 'Normal'}</p>
30
+ </div>
107
31
  </div>
108
32
  );
109
33
  };