@series-inc/venus-sdk 3.0.1 → 3.0.3

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 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:
@@ -3544,7 +3544,7 @@ function initializeTime(venusApi, host) {
3544
3544
  }
3545
3545
 
3546
3546
  // src/version.ts
3547
- var SDK_VERSION = "3.0.1";
3547
+ var SDK_VERSION = "3.0.3";
3548
3548
 
3549
3549
  // src/shared-assets/consts.ts
3550
3550
  var BurgerTimeAssetsCdnPath = "burger-time/Core.stow";
@@ -4793,8 +4793,15 @@ var MockHost = class {
4793
4793
  }
4794
4794
  initialize(options) {
4795
4795
  this._isInitialized = true;
4796
+ const controls = this.updateUiControls();
4796
4797
  return Promise.resolve({
4797
- initializeAsleep: false
4798
+ initializeAsleep: false,
4799
+ hudInsets: {
4800
+ top: controls.feedHeader.height,
4801
+ bottom: 0,
4802
+ left: 0,
4803
+ right: 0
4804
+ }
4798
4805
  });
4799
4806
  }
4800
4807
  updateUiControls() {
@@ -4947,6 +4954,7 @@ var MockHost = class {
4947
4954
  tryResume() {
4948
4955
  if (this.state === 1 /* PAUSED */) {
4949
4956
  this.triggerLifecycleEvent("RESUME" /* RESUME */);
4957
+ this.state = 0 /* PLAYING */;
4950
4958
  }
4951
4959
  }
4952
4960
  async showAdOverlay(type) {
@@ -5281,5 +5289,5 @@ function initializeSocial(venusApi, host) {
5281
5289
  }
5282
5290
 
5283
5291
  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 };
5284
- //# sourceMappingURL=chunk-354W7EXH.mjs.map
5285
- //# sourceMappingURL=chunk-354W7EXH.mjs.map
5292
+ //# sourceMappingURL=chunk-JO6V5EXF.mjs.map
5293
+ //# sourceMappingURL=chunk-JO6V5EXF.mjs.map