ps99-api 2.3.3 → 2.5.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.
- package/.github/workflows/release-on-main.yml +1 -2
- package/.idea/node-ps99-api.iml +1 -0
- package/.idea/runConfigurations/test_changing.xml +1 -1
- package/README.md +1 -1
- package/debug_currency.json +57 -0
- package/debug_goals.json +271 -0
- package/dist/ps99-api.d.ts +2 -0
- package/dist/ps99-api.js +4 -1
- package/dist/ps99-api.js.map +1 -1
- package/dist/request-client/axios.js +6 -1
- package/dist/request-client/axios.js.map +1 -1
- package/dist/responses/collection/achievement.d.ts +2 -0
- package/dist/responses/collection/guild-battle.d.ts +2 -4
- package/dist/responses/collection/index.d.ts +1 -0
- package/dist/responses/collection/index.js +15 -0
- package/dist/responses/collection/index.js.map +1 -1
- package/dist/responses/collection/rank.d.ts +1 -0
- package/dist/responses/collection/rarity.d.ts +1 -0
- package/dist/responses/collection/seed.d.ts +1 -0
- package/dist/responses/exists.d.ts +2 -0
- package/example-web/react/package-lock.json +1504 -1470
- package/example-web/react2/package-lock.json +3082 -2759
- package/example-web/react2/package.json +6 -1
- package/example-web/react2/public/assets/gold_variant_icon.png +0 -0
- package/example-web/react2/public/assets/hot_cocoa_egg.png +0 -0
- package/example-web/react2/public/index.html +34 -31
- package/example-web/react2/src/App.tsx +6 -9
- package/example-web/react2/src/assets/guild_placeholder.png +0 -0
- package/example-web/react2/src/components/AchievementsComponent.tsx +78 -30
- package/example-web/react2/src/components/BoostsComponent.tsx +18 -14
- package/example-web/react2/src/components/BoothsComponent.tsx +24 -22
- package/example-web/react2/src/components/BoxesComponent.tsx +46 -21
- package/example-web/react2/src/components/BuffsComponent.tsx +83 -13
- package/example-web/react2/src/components/CharmsComponent.tsx +47 -29
- package/example-web/react2/src/components/CollectionConfigIndex.tsx +398 -35
- package/example-web/react2/src/components/CollectionsIndex.tsx +132 -23
- package/example-web/react2/src/components/CollectionsLayout.tsx +50 -0
- package/example-web/react2/src/components/CurrencyComponent.tsx +59 -50
- package/example-web/react2/src/components/DynamicCollectionConfigData.tsx +178 -11
- package/example-web/react2/src/components/EggsComponent.tsx +77 -44
- package/example-web/react2/src/components/EnchantsComponent.tsx +84 -34
- package/example-web/react2/src/components/FishingRodsComponent.tsx +38 -31
- package/example-web/react2/src/components/Footer.tsx +75 -18
- package/example-web/react2/src/components/FruitsComponent.tsx +41 -25
- package/example-web/react2/src/components/GenericFetchComponent.tsx +40 -22
- package/example-web/react2/src/components/GuildBattlesComponent.tsx +93 -65
- package/example-web/react2/src/components/Header.tsx +5 -37
- package/example-web/react2/src/components/HomePage.tsx +16 -16
- package/example-web/react2/src/components/HoverboardsComponent.tsx +25 -37
- package/example-web/react2/src/components/ImageComponent.tsx +255 -45
- package/example-web/react2/src/components/ItemCard.tsx +240 -0
- package/example-web/react2/src/components/LootboxesComponent.tsx +24 -16
- package/example-web/react2/src/components/MasteryComponent.tsx +93 -37
- package/example-web/react2/src/components/MerchantsComponent.tsx +46 -28
- package/example-web/react2/src/components/MiscItemsComponent.tsx +28 -26
- package/example-web/react2/src/components/PetsComponent.tsx +115 -46
- package/example-web/react2/src/components/PotionsComponent.tsx +53 -36
- package/example-web/react2/src/components/RandomEventsComponent.tsx +39 -35
- package/example-web/react2/src/components/RanksComponent.tsx +187 -71
- package/example-web/react2/src/components/RarityComponent.tsx +124 -13
- package/example-web/react2/src/components/RebirthsComponent.tsx +37 -26
- package/example-web/react2/src/components/SecretRoomsComponent.tsx +7 -13
- package/example-web/react2/src/components/SeedsComponent.tsx +45 -32
- package/example-web/react2/src/components/ShovelsComponent.tsx +23 -18
- package/example-web/react2/src/components/Sidebar.tsx +105 -0
- package/example-web/react2/src/components/SprinklersComponent.tsx +27 -19
- package/example-web/react2/src/components/Tooltip.tsx +36 -0
- package/example-web/react2/src/components/UltimatesComponent.tsx +29 -24
- package/example-web/react2/src/components/UpgradesComponent.tsx +99 -55
- package/example-web/react2/src/components/WateringCansComponent.tsx +23 -21
- package/example-web/react2/src/components/WorldsComponent.tsx +27 -24
- package/example-web/react2/src/components/XPPotionsComponent.tsx +29 -19
- package/example-web/react2/src/components/ZoneFlagsComponent.tsx +27 -23
- package/example-web/react2/src/components/ZonesComponent.tsx +56 -73
- package/example-web/react2/src/constants/collectionIcons.ts +29 -0
- package/example-web/react2/src/context/CollectionDataContext.tsx +62 -0
- package/example-web/react2/src/hooks/useExpandableList.ts +38 -0
- package/example-web/react2/src/hooks/useItemResolution.ts +351 -0
- package/example-web/react2/src/index.css +257 -0
- package/example-web/react2/src/index.tsx +2 -1
- package/example-web/react2/temp_model.rbxm +0 -0
- package/example-web/react2/webpack.config.js +103 -47
- package/package.json +11 -11
- package/ranks.json +1 -0
- package/repro_collection_fetch.ts +33 -0
- package/repro_image_fetch.ts +50 -0
- package/src/__tests__/__snapshots__/ps99-api-changes.ts.snap +34841 -10439
- package/src/__tests__/__snapshots__/ps99-api-live.ts.snap +160667 -67217
- package/src/ps99-api.ts +9 -5
- package/src/request-client/axios.ts +6 -2
- package/src/responses/collection/achievement.ts +2 -0
- package/src/responses/collection/guild-battle.ts +2 -4
- package/src/responses/collection/index.ts +1 -0
- package/src/responses/collection/rank.ts +1 -0
- package/src/responses/collection/rarity.ts +1 -0
- package/src/responses/collection/seed.ts +1 -0
- package/src/responses/exists.ts +2 -0
- package/tsconfig.json +1 -1
- package/example-web/react2/public/service-worker.js +0 -63
|
@@ -1,42 +1,49 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { CollectionConfigData } from "ps99-api";
|
|
3
|
-
import
|
|
4
|
-
import
|
|
3
|
+
import ItemCard from "./ItemCard";
|
|
4
|
+
import { useItemResolution } from "../hooks/useItemResolution";
|
|
5
5
|
|
|
6
6
|
const FishingRodsComponent: React.FC<{
|
|
7
|
-
configData
|
|
7
|
+
configData: CollectionConfigData<"FishingRods">;
|
|
8
8
|
}> = ({ configData }) => {
|
|
9
9
|
return (
|
|
10
|
-
<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
<
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
10
|
+
<div className="game-card" style={{ maxWidth: '500px', margin: '0 auto' }}>
|
|
11
|
+
<h2>{configData.DisplayName}</h2>
|
|
12
|
+
|
|
13
|
+
<div style={{ maxWidth: '300px', margin: '0 auto 15px auto' }}>
|
|
14
|
+
<ItemCard
|
|
15
|
+
id={configData.DisplayName}
|
|
16
|
+
amount={1}
|
|
17
|
+
label={configData.DisplayName}
|
|
18
|
+
itemData={{
|
|
19
|
+
icon: configData.Icon,
|
|
20
|
+
rarity: undefined,
|
|
21
|
+
name: configData.DisplayName
|
|
22
|
+
}}
|
|
23
|
+
rarityColor={null}
|
|
24
|
+
/>
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '10px', marginBottom: '20px', textAlign: 'left' }}>
|
|
28
|
+
<p><strong>Chance:</strong> {configData.FishingChance}%</p>
|
|
29
|
+
<p><strong>Currency:</strong> {configData.FishingCurrencyMultiplier}x</p>
|
|
30
|
+
<p><strong>Speed:</strong> {configData.FishingGameSpeedMultiplier}x</p>
|
|
31
|
+
<p><strong>Bar Size:</strong> {configData.BarSize}</p>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<div style={{ borderTop: '1px solid #eee', paddingTop: '15px' }}>
|
|
35
|
+
<h3 style={{ fontSize: '1.1em', marginBottom: '10px' }}>Fishing Odds</h3>
|
|
36
|
+
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '8px', justifyContent: 'center' }}>
|
|
37
|
+
{configData.FishingOdds.map((odds, index) => (
|
|
38
|
+
<span key={index} className="badge" style={{ background: '#e3f2fd', color: '#1565c0', border: '1px solid #90caf9' }}>
|
|
39
|
+
{odds[0]}: {odds[1]}%
|
|
40
|
+
</span>
|
|
41
|
+
))}
|
|
36
42
|
</div>
|
|
37
|
-
|
|
38
|
-
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
39
45
|
);
|
|
40
46
|
};
|
|
41
47
|
|
|
48
|
+
|
|
42
49
|
export default FishingRodsComponent;
|
|
@@ -1,12 +1,49 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { useState, useEffect } from "react";
|
|
2
|
+
import { useOnlineStatus } from "../hooks/useOnlineStatus";
|
|
2
3
|
|
|
3
4
|
const Footer: React.FC = () => {
|
|
5
|
+
const isOnline = useOnlineStatus();
|
|
6
|
+
const [lastUpdate, setLastUpdate] = useState<string | null>(null);
|
|
7
|
+
const [loading, setLoading] = useState(false);
|
|
8
|
+
|
|
9
|
+
const updateLastUpdate = () => {
|
|
10
|
+
setLastUpdate(new Date().toLocaleString());
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
const fetchData = async () => {
|
|
15
|
+
setLoading(true);
|
|
16
|
+
// Simulate a fetch call to update lastUpdate time
|
|
17
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
18
|
+
updateLastUpdate();
|
|
19
|
+
setLoading(false);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
fetchData();
|
|
23
|
+
|
|
24
|
+
window.addEventListener("online", updateLastUpdate);
|
|
25
|
+
window.addEventListener("offline", updateLastUpdate);
|
|
26
|
+
|
|
27
|
+
return () => {
|
|
28
|
+
window.removeEventListener("online", updateLastUpdate);
|
|
29
|
+
window.removeEventListener("offline", updateLastUpdate);
|
|
30
|
+
};
|
|
31
|
+
}, []);
|
|
32
|
+
|
|
4
33
|
return (
|
|
5
|
-
<footer
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
34
|
+
<footer className="game-footer">
|
|
35
|
+
<div
|
|
36
|
+
style={{
|
|
37
|
+
display: "flex",
|
|
38
|
+
justifyContent: "center",
|
|
39
|
+
alignItems: "center",
|
|
40
|
+
marginBottom: "1em",
|
|
41
|
+
}}
|
|
42
|
+
>
|
|
43
|
+
<a
|
|
44
|
+
href="https://badge.fury.io/js/ps99-api"
|
|
45
|
+
style={{ display: "flex", alignItems: "center" }}
|
|
46
|
+
>
|
|
10
47
|
<img
|
|
11
48
|
src="https://badge.fury.io/js/ps99-api.svg"
|
|
12
49
|
alt="npm version"
|
|
@@ -14,25 +51,45 @@ const Footer: React.FC = () => {
|
|
|
14
51
|
/>
|
|
15
52
|
</a>
|
|
16
53
|
|
|
17
|
-
<a
|
|
54
|
+
<a
|
|
55
|
+
href="https://github.com/joekiller/node-ps99-api"
|
|
56
|
+
style={{ display: "flex", alignItems: "center" }}
|
|
57
|
+
>
|
|
18
58
|
<img
|
|
19
59
|
src="https://img.shields.io/badge/source-github-blue?logo=github"
|
|
20
60
|
alt="GitHub source"
|
|
21
61
|
height="18"
|
|
22
62
|
/>
|
|
23
63
|
</a>
|
|
64
|
+
|
|
65
|
+
<div style={{ display: "flex", alignItems: "center", height: "18px" }}>
|
|
66
|
+
{isOnline ? (
|
|
67
|
+
<span style={{ color: "green", lineHeight: "18px" }}>● Online</span>
|
|
68
|
+
) : (
|
|
69
|
+
<span style={{ color: "red", lineHeight: "18px" }}>● Offline</span>
|
|
70
|
+
)}
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
<div style={{ marginBottom: "1em" }}>
|
|
74
|
+
{loading ? (
|
|
75
|
+
<span>♻️ Loading...</span>
|
|
76
|
+
) : (
|
|
77
|
+
<span>Last update: {lastUpdate}</span>
|
|
78
|
+
)}
|
|
79
|
+
</div>
|
|
80
|
+
<div>
|
|
81
|
+
<p>
|
|
82
|
+
© {new Date().getFullYear()} Joseph "
|
|
83
|
+
<a
|
|
84
|
+
href="https://joekiller.com"
|
|
85
|
+
target="_blank"
|
|
86
|
+
rel="noopener noreferrer"
|
|
87
|
+
>
|
|
88
|
+
joekiller
|
|
89
|
+
</a>
|
|
90
|
+
" Lawson. All rights reserved.
|
|
91
|
+
</p>
|
|
24
92
|
</div>
|
|
25
|
-
<p>
|
|
26
|
-
© {new Date().getFullYear()} Joseph "
|
|
27
|
-
<a
|
|
28
|
-
href="https://joekiller.com"
|
|
29
|
-
target="_blank"
|
|
30
|
-
rel="noopener noreferrer"
|
|
31
|
-
>
|
|
32
|
-
joekiller
|
|
33
|
-
</a>
|
|
34
|
-
" Lawson. All rights reserved.
|
|
35
|
-
</p>
|
|
36
93
|
</footer>
|
|
37
94
|
);
|
|
38
95
|
};
|
|
@@ -1,35 +1,51 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { CollectionConfigData } from "ps99-api";
|
|
3
|
-
import
|
|
4
|
-
import
|
|
3
|
+
import ItemCard from "./ItemCard";
|
|
4
|
+
import { useItemResolution } from "../hooks/useItemResolution";
|
|
5
5
|
|
|
6
6
|
const FruitsComponent: React.FC<{
|
|
7
|
-
configData
|
|
7
|
+
configData: CollectionConfigData<"Fruits">;
|
|
8
8
|
}> = ({ configData }) => {
|
|
9
|
+
const { getRarityColor } = useItemResolution();
|
|
10
|
+
const rarityColor = configData.Rarity ? getRarityColor(configData.Rarity) : null;
|
|
11
|
+
|
|
9
12
|
return (
|
|
10
|
-
<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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>Duration: {configData.Duration}s</p>
|
|
27
|
+
{configData.Desc && <p>{configData.Desc}</p>}
|
|
28
|
+
{configData.IgnoreFruitMachine && <p>Ignore Fruit Machine</p>}
|
|
29
|
+
</div>
|
|
30
|
+
<div style={{ marginTop: '15px' }}>
|
|
31
|
+
<h3 style={{ textAlign: 'center', fontSize: '1.1em' }}>Boosts</h3>
|
|
32
|
+
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '8px', justifyContent: 'center' }}>
|
|
33
|
+
{configData.Boost.map((boost, index) => (
|
|
34
|
+
<span key={index} style={{
|
|
35
|
+
background: '#e8f5e9',
|
|
36
|
+
color: '#2e7d32',
|
|
37
|
+
padding: '5px 10px',
|
|
38
|
+
borderRadius: '12px',
|
|
39
|
+
fontSize: '0.9em',
|
|
40
|
+
fontWeight: 'bold',
|
|
41
|
+
border: '1px solid #a5d6a7'
|
|
42
|
+
}}>
|
|
43
|
+
{boost.Type}: {boost.Amount}
|
|
44
|
+
</span>
|
|
45
|
+
))}
|
|
30
46
|
</div>
|
|
31
|
-
|
|
32
|
-
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
33
49
|
);
|
|
34
50
|
};
|
|
35
51
|
|
|
@@ -1,45 +1,55 @@
|
|
|
1
1
|
import React, { useEffect, useState, ReactNode } from "react";
|
|
2
|
-
import { useParams } from "react-router-dom";
|
|
3
2
|
import { PetSimulator99API, ApiResponseBody, CollectionName } from "ps99-api";
|
|
4
3
|
|
|
5
4
|
interface GenericFetchComponentProps<T> {
|
|
6
5
|
collectionName: CollectionName;
|
|
6
|
+
configName: string;
|
|
7
7
|
render: (data: T) => ReactNode;
|
|
8
|
-
configData?: T;
|
|
9
8
|
}
|
|
10
9
|
|
|
11
10
|
export const GenericFetchComponent = <T,>({
|
|
12
11
|
collectionName,
|
|
12
|
+
configName,
|
|
13
13
|
render,
|
|
14
|
-
configData,
|
|
15
14
|
}: GenericFetchComponentProps<T>) => {
|
|
16
|
-
const
|
|
17
|
-
const [data, setData] = useState<T | null>(configData || null);
|
|
15
|
+
const [data, setData] = useState<T | null>(null);
|
|
18
16
|
const [error, setError] = useState<string | null>(null);
|
|
19
17
|
|
|
20
18
|
useEffect(() => {
|
|
21
|
-
|
|
19
|
+
let isMounted = true;
|
|
22
20
|
|
|
23
21
|
const fetchData = async () => {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
22
|
+
try {
|
|
23
|
+
const api = new PetSimulator99API();
|
|
24
|
+
const response: ApiResponseBody<any[]> =
|
|
25
|
+
await api.getCollection(collectionName);
|
|
26
|
+
if (isMounted) {
|
|
27
|
+
if (response.status === "ok") {
|
|
28
|
+
const item = response.data.find(
|
|
29
|
+
(item) => item.configName === configName,
|
|
30
|
+
);
|
|
31
|
+
if (item) {
|
|
32
|
+
setData(item.configData);
|
|
33
|
+
} else {
|
|
34
|
+
setError("Configuration not found");
|
|
35
|
+
}
|
|
36
|
+
} else {
|
|
37
|
+
setError(response.error.message);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
} catch (err) {
|
|
41
|
+
if (isMounted) {
|
|
42
|
+
setError(err.message);
|
|
36
43
|
}
|
|
37
|
-
} else {
|
|
38
|
-
setError(response.error.message);
|
|
39
44
|
}
|
|
40
45
|
};
|
|
46
|
+
|
|
41
47
|
fetchData();
|
|
42
|
-
|
|
48
|
+
|
|
49
|
+
return () => {
|
|
50
|
+
isMounted = false;
|
|
51
|
+
};
|
|
52
|
+
}, [collectionName, configName]);
|
|
43
53
|
|
|
44
54
|
if (error) {
|
|
45
55
|
return <div>Error: {error}</div>;
|
|
@@ -49,5 +59,13 @@ export const GenericFetchComponent = <T,>({
|
|
|
49
59
|
return <div>Loading...</div>;
|
|
50
60
|
}
|
|
51
61
|
|
|
52
|
-
return
|
|
62
|
+
return (
|
|
63
|
+
<div style={{
|
|
64
|
+
width: '100%',
|
|
65
|
+
padding: '20px',
|
|
66
|
+
boxSizing: 'border-box'
|
|
67
|
+
}}>
|
|
68
|
+
{render(data)}
|
|
69
|
+
</div>
|
|
70
|
+
);
|
|
53
71
|
};
|
|
@@ -1,75 +1,103 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { CollectionConfigData } from "ps99-api";
|
|
3
|
-
import
|
|
2
|
+
import { CollectionConfigData, GuildBattlePlacementReward, GuildBattleRewardItem } from "ps99-api";
|
|
3
|
+
import DynamicCollectionConfigData from "./DynamicCollectionConfigData";
|
|
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";
|
|
9
|
+
|
|
10
|
+
const rewardTypes = ["Clan Gift", "Booth", "Hoverboard", "Pet"];
|
|
4
11
|
|
|
5
12
|
const GuildBattlesComponent: React.FC<{
|
|
6
|
-
configData
|
|
13
|
+
configData: CollectionConfigData<"GuildBattles">;
|
|
7
14
|
}> = ({ configData }) => {
|
|
15
|
+
const { resolveItem, getRarityColor, loading } = useItemResolution();
|
|
16
|
+
|
|
17
|
+
if (loading) return <div>Loading data...</div>;
|
|
18
|
+
|
|
19
|
+
const renderRewardItem = (reward: GuildBattlePlacementReward | GuildBattleRewardItem, index: number) => {
|
|
20
|
+
let id: string;
|
|
21
|
+
let amount = 1; // Default amount
|
|
22
|
+
let pt: number | undefined;
|
|
23
|
+
|
|
24
|
+
if ("Item" in reward) { // GuildBattlePlacementReward
|
|
25
|
+
id = reward.Item._data.id;
|
|
26
|
+
pt = reward.Item._data.pt;
|
|
27
|
+
amount = (reward.Item._data as any)._am || 1;
|
|
28
|
+
} else { // GuildBattleRewardItem
|
|
29
|
+
id = reward._data.id;
|
|
30
|
+
amount = (reward._data as any)._am || 1;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Try to resolve the item using the hook
|
|
34
|
+
const itemData = resolveItem(id, pt);
|
|
35
|
+
const rarityColor = itemData?.rarity ? getRarityColor(itemData.rarity) : null;
|
|
36
|
+
|
|
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
|
+
);
|
|
48
|
+
};
|
|
49
|
+
|
|
8
50
|
return (
|
|
9
|
-
<
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
<h4>
|
|
42
|
-
<
|
|
43
|
-
{
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
<p>Item ID: {reward._data.id}</p>
|
|
54
|
-
</li>
|
|
51
|
+
<div style={{ padding: "1em", border: "1px solid #ccc", borderRadius: "8px", marginBottom: "2em" }}>
|
|
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>
|
|
58
|
+
<p><strong>Start Time:</strong> {new Date(configData.StartTime * 1000).toLocaleString()}</p>
|
|
59
|
+
<p><strong>Finish Time:</strong> {new Date(configData.FinishTime * 1000).toLocaleString()}</p>
|
|
60
|
+
{configData.HasGoals && <p><strong>Has Goals:</strong> Yes</p>}
|
|
61
|
+
|
|
62
|
+
<h3>Placement Rewards:</h3>
|
|
63
|
+
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '1em' }}>
|
|
64
|
+
{configData.PlacementRewards?.map((reward, index) => (
|
|
65
|
+
<div key={index} style={{
|
|
66
|
+
flex: '1 1 300px', // Allow flex but with base width
|
|
67
|
+
maxWidth: '350px',
|
|
68
|
+
margin: '0 auto'
|
|
69
|
+
}}>
|
|
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>
|
|
75
|
+
</div>
|
|
76
|
+
))}
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
<h3>Rewards:</h3>
|
|
80
|
+
{["Gold", "Silver", "Bronze", "Good"].map(tier => (
|
|
81
|
+
configData.Rewards[tier]?.length > 0 && (
|
|
82
|
+
<div key={tier}>
|
|
83
|
+
<h4>{tier}</h4>
|
|
84
|
+
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '1em' }}>
|
|
85
|
+
{configData.Rewards[tier].map((reward, index) => (
|
|
86
|
+
<div key={index} style={{
|
|
87
|
+
border: '1px solid #ccc',
|
|
88
|
+
borderRadius: '8px',
|
|
89
|
+
padding: '1em',
|
|
90
|
+
flex: '1 1 calc(33% - 1em)',
|
|
91
|
+
boxSizing: 'border-box',
|
|
92
|
+
}}>
|
|
93
|
+
{renderRewardItem(reward, index)}
|
|
94
|
+
</div>
|
|
55
95
|
))}
|
|
56
|
-
</
|
|
57
|
-
{data.Rewards.Good && (
|
|
58
|
-
<div>
|
|
59
|
-
<h4>Good:</h4>
|
|
60
|
-
<ul>
|
|
61
|
-
{data.Rewards.Good.map((reward, index) => (
|
|
62
|
-
<li key={index}>
|
|
63
|
-
<p>Item ID: {reward._data.id}</p>
|
|
64
|
-
</li>
|
|
65
|
-
))}
|
|
66
|
-
</ul>
|
|
67
|
-
</div>
|
|
68
|
-
)}
|
|
96
|
+
</div>
|
|
69
97
|
</div>
|
|
70
|
-
|
|
71
|
-
)}
|
|
72
|
-
|
|
98
|
+
)
|
|
99
|
+
))}
|
|
100
|
+
</div>
|
|
73
101
|
);
|
|
74
102
|
};
|
|
75
103
|
|
|
@@ -6,22 +6,12 @@ const Header: React.FC = () => {
|
|
|
6
6
|
const pathnames = location.pathname.split("/").filter((x) => x);
|
|
7
7
|
|
|
8
8
|
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
|
-
>
|
|
9
|
+
<nav className="game-header">
|
|
19
10
|
<div style={{ display: "flex", alignItems: "center" }}>
|
|
20
11
|
<Link
|
|
21
12
|
to="/"
|
|
22
13
|
style={{
|
|
23
14
|
textDecoration: "none",
|
|
24
|
-
color: "#007bff",
|
|
25
15
|
display: "flex",
|
|
26
16
|
alignItems: "center",
|
|
27
17
|
}}
|
|
@@ -29,35 +19,13 @@ const Header: React.FC = () => {
|
|
|
29
19
|
<img
|
|
30
20
|
src="/node-ps99-api/icons/icon-192x192.png"
|
|
31
21
|
alt="Home"
|
|
32
|
-
style={{ width: "40px", height: "40px", marginRight: "0.5em" }}
|
|
22
|
+
style={{ width: "40px", height: "40px", marginRight: "0.5em", border: "2px solid white", borderRadius: "50%" }}
|
|
33
23
|
/>
|
|
34
24
|
</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
|
|
41
|
-
</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>
|
|
57
25
|
</div>
|
|
58
|
-
<h1 style={{ margin: 0 }}>
|
|
59
|
-
<Link to="/"
|
|
60
|
-
Pet Simulator 99
|
|
26
|
+
<h1 style={{ margin: 0, fontSize: '1.5rem', color: 'white' }}>
|
|
27
|
+
<Link to="/">
|
|
28
|
+
Pet Simulator 99
|
|
61
29
|
</Link>
|
|
62
30
|
</h1>
|
|
63
31
|
</nav>
|
|
@@ -3,22 +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: "
|
|
7
|
-
<h1
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
</
|
|
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.
|
|
12
|
+
</p>
|
|
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>
|
|
22
22
|
</div>
|
|
23
23
|
);
|
|
24
24
|
};
|