@series-inc/venus-sdk 3.0.2 → 3.0.4
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/README.md +186 -0
- package/dist/{chunk-NQGU2VZM.mjs → chunk-PXWCNWJ6.mjs} +8 -6
- package/dist/chunk-PXWCNWJ6.mjs.map +1 -0
- package/dist/index.cjs +6 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/venus-api/index.cjs +6 -4
- package/dist/venus-api/index.cjs.map +1 -1
- package/dist/venus-api/index.mjs +1 -1
- package/package.json +1 -1
- package/dist/chunk-NQGU2VZM.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -690,6 +690,192 @@ VenusAPI.logging.debug('Debug info')
|
|
|
690
690
|
|
|
691
691
|
---
|
|
692
692
|
|
|
693
|
+
### Leaderboard API (BETA)
|
|
694
|
+
|
|
695
|
+
Competitive leaderboards with anti-cheat, multiple modes, and time periods.
|
|
696
|
+
|
|
697
|
+
#### API Methods
|
|
698
|
+
|
|
699
|
+
```typescript
|
|
700
|
+
// Start a leaderboard session
|
|
701
|
+
const session = await VenusAPI.leaderboard.startRunAsync({
|
|
702
|
+
mode: 'classic' // Optional: 'classic', 'hard', etc. Defaults to 'default'
|
|
703
|
+
})
|
|
704
|
+
// Returns: { sessionId, startTime, expiresAt, hashNonce?, mode }
|
|
705
|
+
|
|
706
|
+
// Submit a score (within 1 hour of starting session)
|
|
707
|
+
const result = await VenusAPI.leaderboard.submitScoreAsync({
|
|
708
|
+
sessionId: session.sessionId,
|
|
709
|
+
score: 1500,
|
|
710
|
+
durationSec: 120,
|
|
711
|
+
mode: 'classic', // Optional: must match session mode
|
|
712
|
+
metadata: { // Optional: game-specific data (max 20KB)
|
|
713
|
+
levelCompleted: 10,
|
|
714
|
+
powerUpsUsed: 3
|
|
715
|
+
},
|
|
716
|
+
telemetry: { // Optional: anti-cheat data (max 2KB, primitives only)
|
|
717
|
+
clickCount: 245,
|
|
718
|
+
avgReactionTime: 0.32
|
|
719
|
+
},
|
|
720
|
+
hash: computedHash // Required if leaderboard uses hash verification
|
|
721
|
+
})
|
|
722
|
+
// Returns: { accepted, rank, zScore, isAnomaly }
|
|
723
|
+
|
|
724
|
+
// Get leaderboard (paginated)
|
|
725
|
+
const leaderboard = await VenusAPI.leaderboard.getLeaderboardAsync({
|
|
726
|
+
mode: 'classic', // Optional: game mode
|
|
727
|
+
period: 'daily', // Optional: 'daily', 'weekly', 'monthly', 'alltime'
|
|
728
|
+
periodDate: Date.now(), // Optional: specific period to view
|
|
729
|
+
limit: 50, // Optional: entries per page (max 50)
|
|
730
|
+
cursor: nextCursor // Optional: for pagination
|
|
731
|
+
})
|
|
732
|
+
// Returns: {
|
|
733
|
+
// variant: 'standard',
|
|
734
|
+
// entries: [{ profileId, username, avatarUrl, score, rank, ... }],
|
|
735
|
+
// totalEntries: 1234,
|
|
736
|
+
// nextCursor: 'abc123...',
|
|
737
|
+
// playerRank: 42,
|
|
738
|
+
// periodInstance: 'daily_2025-11-04'
|
|
739
|
+
// }
|
|
740
|
+
|
|
741
|
+
// Get leaderboard highlight (top players + context around you)
|
|
742
|
+
const highlight = await VenusAPI.leaderboard.getLeaderboardHighlightAsync({
|
|
743
|
+
mode: 'classic',
|
|
744
|
+
period: 'daily',
|
|
745
|
+
topCount: 3, // Top N players (podium)
|
|
746
|
+
contextAhead: 4, // Players ahead of you
|
|
747
|
+
contextBehind: 2 // Players behind you
|
|
748
|
+
})
|
|
749
|
+
// Returns: {
|
|
750
|
+
// variant: 'highlight',
|
|
751
|
+
// entries: [...],
|
|
752
|
+
// context: {
|
|
753
|
+
// topEntries: [...], // Top 3
|
|
754
|
+
// beforePlayer: [...], // 4 players ahead
|
|
755
|
+
// playerEntry: {...}, // Your entry
|
|
756
|
+
// afterPlayer: [...], // 2 players behind
|
|
757
|
+
// omittedBefore: 35, // Gap between top 3 and you
|
|
758
|
+
// omittedAfter: 100 // Players below you
|
|
759
|
+
// },
|
|
760
|
+
// playerRank: 42,
|
|
761
|
+
// totalEntries: 150
|
|
762
|
+
// }
|
|
763
|
+
|
|
764
|
+
// Get player stats
|
|
765
|
+
const stats = await VenusAPI.leaderboard.getPlayerStatsAsync({
|
|
766
|
+
mode: 'classic',
|
|
767
|
+
period: 'daily'
|
|
768
|
+
})
|
|
769
|
+
// Returns: {
|
|
770
|
+
// rank: 42,
|
|
771
|
+
// score: 1500,
|
|
772
|
+
// totalPlayers: 150,
|
|
773
|
+
// percentile: 0.72, // 72nd percentile
|
|
774
|
+
// trustScore: 85,
|
|
775
|
+
// periodInstance: 'daily_2025-11-04'
|
|
776
|
+
// }
|
|
777
|
+
```
|
|
778
|
+
|
|
779
|
+
#### Configuration
|
|
780
|
+
|
|
781
|
+
Add a `leaderboard` object to your game's `config.json` file:
|
|
782
|
+
|
|
783
|
+
```json
|
|
784
|
+
{
|
|
785
|
+
"leaderboard": {
|
|
786
|
+
"isDisabled": false,
|
|
787
|
+
"disabledMessage": "Leaderboards are temporarily unavailable.",
|
|
788
|
+
"requiresHash": true,
|
|
789
|
+
"hashSecret": "your-secret-key-change-in-production",
|
|
790
|
+
"scoringFields": ["score", "durationSec", "sessionId"],
|
|
791
|
+
"minDurationSec": 10,
|
|
792
|
+
"maxDurationSec": 600,
|
|
793
|
+
"minScore": 0,
|
|
794
|
+
"maxScore": 999999999,
|
|
795
|
+
"modes": {
|
|
796
|
+
"default": {
|
|
797
|
+
"displayName": "Classic Mode"
|
|
798
|
+
},
|
|
799
|
+
"hard": {
|
|
800
|
+
"displayName": "Hard Mode",
|
|
801
|
+
"minDurationSec": 5,
|
|
802
|
+
"maxDurationSec": 300
|
|
803
|
+
}
|
|
804
|
+
},
|
|
805
|
+
"periods": {
|
|
806
|
+
"daily": {
|
|
807
|
+
"displayName": "Daily",
|
|
808
|
+
"type": "daily"
|
|
809
|
+
},
|
|
810
|
+
"alltime": {
|
|
811
|
+
"displayName": "All Time",
|
|
812
|
+
"type": "alltime"
|
|
813
|
+
}
|
|
814
|
+
},
|
|
815
|
+
"antiCheat": {
|
|
816
|
+
"enableZScoreDetection": false,
|
|
817
|
+
"zScoreThreshold": 3,
|
|
818
|
+
"enableRateLimit": true,
|
|
819
|
+
"minTimeBetweenSubmissionsSec": 60,
|
|
820
|
+
"trustScoreDecayPerFlag": 10,
|
|
821
|
+
"shadowBanThreshold": 20
|
|
822
|
+
},
|
|
823
|
+
"displaySettings": {
|
|
824
|
+
"maxEntriesPerPage": 50
|
|
825
|
+
},
|
|
826
|
+
"seedEntries": {
|
|
827
|
+
"default": {
|
|
828
|
+
"daily": [
|
|
829
|
+
{
|
|
830
|
+
"score": 18500,
|
|
831
|
+
"username": "ProPlayer",
|
|
832
|
+
"avatarUrl": null,
|
|
833
|
+
"durationSec": 180
|
|
834
|
+
},
|
|
835
|
+
{
|
|
836
|
+
"score": 15200,
|
|
837
|
+
"username": "Challenger",
|
|
838
|
+
"avatarUrl": null,
|
|
839
|
+
"durationSec": 210
|
|
840
|
+
}
|
|
841
|
+
]
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
```
|
|
847
|
+
|
|
848
|
+
**Configuration Options:**
|
|
849
|
+
|
|
850
|
+
- `isDisabled`: Globally disable leaderboards
|
|
851
|
+
- `requiresHash`: Enable HMAC-based score verification (recommended for production)
|
|
852
|
+
- `hashSecret`: Secret key for HMAC verification (keep this secure!)
|
|
853
|
+
- `scoringFields`: Fields included in hash verification (can include nested fields like `metadata.level`)
|
|
854
|
+
- `minDurationSec` / `maxDurationSec`: Valid gameplay duration range
|
|
855
|
+
- `minScore` / `maxScore`: Valid score bounds
|
|
856
|
+
- `modes`: Game modes (can override min/max values per mode)
|
|
857
|
+
- `periods`: Time periods for leaderboards (`daily`, `weekly`, `monthly`, `alltime`)
|
|
858
|
+
- `antiCheat`: Anti-cheat settings
|
|
859
|
+
- `seedEntries`: Pre-populate leaderboards with NPC scores (nested by mode → period)
|
|
860
|
+
|
|
861
|
+
**Features:**
|
|
862
|
+
- **Multiple Modes**: Support different game modes (classic, hard, etc.)
|
|
863
|
+
- **Time Periods**: Daily, weekly, monthly, and all-time leaderboards
|
|
864
|
+
- **Anti-Cheat**: Session validation, rate limiting, hash verification, z-score anomaly detection
|
|
865
|
+
- **Shadow Banning**: Cheaters see their own scores but are hidden from others
|
|
866
|
+
- **Trust Scores**: Per-player reputation that decays with suspicious behavior
|
|
867
|
+
- **Seed Entries**: Pre-populate leaderboards with NPC scores
|
|
868
|
+
- **Pagination**: Cursor-based pagination for large leaderboards
|
|
869
|
+
- **UTC-Based Periods**: All players globally compete in same daily/weekly/monthly periods
|
|
870
|
+
|
|
871
|
+
**Security Notes:**
|
|
872
|
+
- Session tokens expire after 1 hour and can only be used once to prevent replay attacks
|
|
873
|
+
- Use `requiresHash: true` in production with a strong `hashSecret`
|
|
874
|
+
- Keep `hashSecret` out of version control (use environment variables or local config)
|
|
875
|
+
- Store `hashSecret` in `config.local.json` (gitignored) for local development
|
|
876
|
+
|
|
877
|
+
---
|
|
878
|
+
|
|
693
879
|
## Mock Mode
|
|
694
880
|
|
|
695
881
|
All APIs have complete mock implementations for local development:
|
|
@@ -1160,7 +1160,8 @@ var MockCdnApi = class {
|
|
|
1160
1160
|
return index === pathParts.length - 1 ? encodeURIComponent(part) : part;
|
|
1161
1161
|
});
|
|
1162
1162
|
const encodedSubPath = encodedParts.join("/");
|
|
1163
|
-
const
|
|
1163
|
+
const cacheBust = Date.now();
|
|
1164
|
+
const fullUrl = `${this.baseUrl}${encodedSubPath}?cacheBust=${cacheBust}`;
|
|
1164
1165
|
return fullUrl;
|
|
1165
1166
|
}
|
|
1166
1167
|
resolveAvatarAssetUrl(subPath) {
|
|
@@ -1553,10 +1554,10 @@ function initializeLifecycleApi(venusApi, host) {
|
|
|
1553
1554
|
// src/logging/MockLoggingApi.ts
|
|
1554
1555
|
var MockLoggingApi = class {
|
|
1555
1556
|
logDebug(message, ...args) {
|
|
1556
|
-
console.log(`[Venus Mock] ${message}`, args);
|
|
1557
|
+
console.log(`[Venus Mock] ${message}`, ...args);
|
|
1557
1558
|
}
|
|
1558
1559
|
logError(message, ...args) {
|
|
1559
|
-
console.error(`[Venus Mock] ${message}`, args);
|
|
1560
|
+
console.error(`[Venus Mock] ${message}`, ...args);
|
|
1560
1561
|
}
|
|
1561
1562
|
};
|
|
1562
1563
|
|
|
@@ -3544,7 +3545,7 @@ function initializeTime(venusApi, host) {
|
|
|
3544
3545
|
}
|
|
3545
3546
|
|
|
3546
3547
|
// src/version.ts
|
|
3547
|
-
var SDK_VERSION = "3.0.
|
|
3548
|
+
var SDK_VERSION = "3.0.4";
|
|
3548
3549
|
|
|
3549
3550
|
// src/shared-assets/consts.ts
|
|
3550
3551
|
var BurgerTimeAssetsCdnPath = "burger-time/Core.stow";
|
|
@@ -4954,6 +4955,7 @@ var MockHost = class {
|
|
|
4954
4955
|
tryResume() {
|
|
4955
4956
|
if (this.state === 1 /* PAUSED */) {
|
|
4956
4957
|
this.triggerLifecycleEvent("RESUME" /* RESUME */);
|
|
4958
|
+
this.state = 0 /* PLAYING */;
|
|
4957
4959
|
}
|
|
4958
4960
|
}
|
|
4959
4961
|
async showAdOverlay(type) {
|
|
@@ -5288,5 +5290,5 @@ function initializeSocial(venusApi, host) {
|
|
|
5288
5290
|
}
|
|
5289
5291
|
|
|
5290
5292
|
export { HapticFeedbackStyle, HostCdnApi, HostProfileApi, HostTimeApi, MockAdsApi, MockAiApi, MockAnalyticsApi, MockAvatarApi, MockCdnApi, MockFeaturesApi, MockHapticsApi, MockIapApi, MockLeaderboardApi, MockLifecycleApi, MockLoggingApi, MockNavigationApi, MockNotificationsApi, MockPopupsApi, MockPreloaderApi, MockProfileApi, MockSharedAssetsApi, MockSimulationApi, MockSocialApi, MockStorageApi, MockTimeApi, RemoteHost, RpcAdsApi, RpcAiApi, RpcAnalyticsApi, RpcAvatarApi, RpcClient, RpcFeaturesApi, RpcHapticsApi, RpcIapApi, RpcLeaderboardApi, RpcLifecycleApi, RpcLoggingApi, RpcNavigationApi, RpcNotificationsApi, RpcPopupsApi, RpcPreloaderApi, RpcSharedAssetsApi, RpcSimulationApi, RpcSocialApi, RpcStorageApi, SDK_VERSION, VenusMessageId, VenusRoom, createHost, createMockStorageApi, init_rooms, initializeAds, initializeAi, initializeAnalytics, initializeAvatar3d, initializeCdn, initializeFeaturesApi, initializeHaptics, initializeIap, initializeLeaderboard, initializeLifecycleApi, initializeLocalNotifications, initializeLoggingApi, initializePopups, initializePost, initializePreloader, initializeProfile, initializeRoomsApi, initializeSimulation, initializeSocial, initializeStackNavigation, initializeStorage, initializeTime, isPacificDaylightTime, setupRoomNotifications };
|
|
5291
|
-
//# sourceMappingURL=chunk-
|
|
5292
|
-
//# sourceMappingURL=chunk-
|
|
5293
|
+
//# sourceMappingURL=chunk-PXWCNWJ6.mjs.map
|
|
5294
|
+
//# sourceMappingURL=chunk-PXWCNWJ6.mjs.map
|