@series-inc/venus-sdk 3.1.2-beta.1 → 3.1.2

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 (38) hide show
  1. package/dist/{AdsApi-DFutZ7_q.d.mts → AdsApi-CNGRf6j0.d.mts} +293 -501
  2. package/dist/{AdsApi-DFutZ7_q.d.ts → AdsApi-CNGRf6j0.d.ts} +293 -501
  3. package/dist/{chunk-U6NFOU3E.mjs → chunk-PXWCNWJ6.mjs} +1525 -1380
  4. package/dist/chunk-PXWCNWJ6.mjs.map +1 -0
  5. package/dist/{chunk-QABXMFND.mjs → chunk-W7IPHM67.mjs} +26 -3
  6. package/dist/chunk-W7IPHM67.mjs.map +1 -0
  7. package/dist/core-R3FHW62G.mjs +3 -0
  8. package/dist/{core-62LWDHN7.mjs.map → core-R3FHW62G.mjs.map} +1 -1
  9. package/dist/index.cjs +1531 -1406
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.d.mts +92 -280
  12. package/dist/index.d.ts +92 -280
  13. package/dist/index.mjs +6 -4
  14. package/dist/index.mjs.map +1 -1
  15. package/dist/venus-api/index.cjs +2012 -1548
  16. package/dist/venus-api/index.cjs.map +1 -1
  17. package/dist/venus-api/index.d.mts +2 -2
  18. package/dist/venus-api/index.d.ts +2 -2
  19. package/dist/venus-api/index.mjs +391 -92
  20. package/dist/venus-api/index.mjs.map +1 -1
  21. package/package.json +1 -1
  22. package/dist/chunk-NSSMTXJJ.mjs +0 -7
  23. package/dist/chunk-NSSMTXJJ.mjs.map +0 -1
  24. package/dist/chunk-QABXMFND.mjs.map +0 -1
  25. package/dist/chunk-U6NFOU3E.mjs.map +0 -1
  26. package/dist/chunk-UXY5CKKG.mjs +0 -12
  27. package/dist/chunk-UXY5CKKG.mjs.map +0 -1
  28. package/dist/core-62LWDHN7.mjs +0 -4
  29. package/dist/vite/index.cjs +0 -534
  30. package/dist/vite/index.cjs.map +0 -1
  31. package/dist/vite/index.mjs +0 -527
  32. package/dist/vite/index.mjs.map +0 -1
  33. package/dist/webview/index.cjs +0 -15
  34. package/dist/webview/index.cjs.map +0 -1
  35. package/dist/webview/index.d.mts +0 -15
  36. package/dist/webview/index.d.ts +0 -15
  37. package/dist/webview/index.mjs +0 -4
  38. package/dist/webview/index.mjs.map +0 -1
@@ -1,7 +1,9 @@
1
1
  'use strict';
2
2
 
3
3
  var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
7
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6
8
  var __esm = (fn, res) => function __init() {
7
9
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
@@ -10,6 +12,15 @@ var __export = (target, all) => {
10
12
  for (var name in all)
11
13
  __defProp(target, name, { get: all[name], enumerable: true });
12
14
  };
15
+ var __copyProps = (to, from, except, desc) => {
16
+ if (from && typeof from === "object" || typeof from === "function") {
17
+ for (let key of __getOwnPropNames(from))
18
+ if (!__hasOwnProp.call(to, key) && key !== except)
19
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
20
+ }
21
+ return to;
22
+ };
23
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
13
24
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
14
25
 
15
26
  // src/venus-api/systems/core.js
@@ -100,6 +111,221 @@ var init_core = __esm({
100
111
  }
101
112
  });
102
113
 
114
+ // src/rooms/RoomsApi.ts
115
+ var init_RoomsApi = __esm({
116
+ "src/rooms/RoomsApi.ts"() {
117
+ }
118
+ });
119
+
120
+ // src/rooms/VenusRoom.ts
121
+ var VenusRoom;
122
+ var init_VenusRoom = __esm({
123
+ "src/rooms/VenusRoom.ts"() {
124
+ VenusRoom = class {
125
+ constructor(roomData) {
126
+ __publicField(this, "id");
127
+ __publicField(this, "name");
128
+ __publicField(this, "players");
129
+ __publicField(this, "maxPlayers");
130
+ __publicField(this, "gameType");
131
+ __publicField(this, "appId");
132
+ __publicField(this, "type");
133
+ __publicField(this, "createdBy");
134
+ __publicField(this, "createdAt");
135
+ __publicField(this, "updatedAt");
136
+ __publicField(this, "isPrivate");
137
+ __publicField(this, "currentPlayers");
138
+ __publicField(this, "status");
139
+ __publicField(this, "customMetadata");
140
+ __publicField(this, "admins");
141
+ __publicField(this, "roomCode");
142
+ __publicField(this, "description");
143
+ __publicField(this, "data");
144
+ __publicField(this, "version");
145
+ __publicField(this, "_subscriptions", /* @__PURE__ */ new Map());
146
+ this.id = roomData.id;
147
+ this.name = roomData.name;
148
+ this.players = roomData.currentPlayers || [];
149
+ this.maxPlayers = roomData.maxPlayers;
150
+ this.gameType = roomData.gameType;
151
+ this.appId = roomData.appId;
152
+ this.type = roomData.type;
153
+ this.createdBy = roomData.createdBy;
154
+ this.createdAt = roomData.createdAt;
155
+ this.updatedAt = roomData.updatedAt;
156
+ this.isPrivate = roomData.isPrivate;
157
+ this.currentPlayers = roomData.currentPlayers || [];
158
+ this.status = roomData.status;
159
+ this.customMetadata = roomData.customMetadata || {};
160
+ this.admins = roomData.admins || [];
161
+ this.roomCode = roomData.roomCode;
162
+ this.description = roomData.description;
163
+ this.data = roomData.data || {};
164
+ this.version = roomData.version;
165
+ console.log(`VenusRoom: Created room object for ${this.id}`, {
166
+ hasCustomMetadata: !!this.customMetadata,
167
+ hasGameState: !!this.customMetadata?.rules?.gameState,
168
+ gamePhase: this.customMetadata?.rules?.gameState?.phase,
169
+ currentPlayer: this.customMetadata?.rules?.gameState?.currentPlayer
170
+ });
171
+ }
172
+ updateFromRoomData(newRoomData) {
173
+ if (newRoomData.id === this.id) {
174
+ this.name = newRoomData.name || this.name;
175
+ this.players = newRoomData.currentPlayers || this.players;
176
+ this.maxPlayers = newRoomData.maxPlayers || this.maxPlayers;
177
+ this.gameType = newRoomData.gameType || this.gameType;
178
+ this.currentPlayers = newRoomData.currentPlayers || this.currentPlayers;
179
+ this.customMetadata = newRoomData.customMetadata || this.customMetadata;
180
+ this.data = newRoomData.data || this.data;
181
+ this.status = newRoomData.status || this.status;
182
+ this.updatedAt = newRoomData.updatedAt || this.updatedAt;
183
+ console.log(`VenusRoom: Updated room object ${this.id} with fresh data`, {
184
+ hasCustomMetadata: !!this.customMetadata,
185
+ hasGameState: !!this.customMetadata?.rules?.gameState,
186
+ gamePhase: this.customMetadata?.rules?.gameState?.phase,
187
+ currentPlayer: this.customMetadata?.rules?.gameState?.currentPlayer
188
+ });
189
+ }
190
+ }
191
+ };
192
+ }
193
+ });
194
+
195
+ // src/rooms/index.ts
196
+ var rooms_exports = {};
197
+ __export(rooms_exports, {
198
+ VenusRoom: () => VenusRoom,
199
+ initializeRoomsApi: () => initializeRoomsApi,
200
+ setupRoomNotifications: () => setupRoomNotifications
201
+ });
202
+ function bindMethod(target, targetKey, source, sourceKey) {
203
+ const key = sourceKey ?? targetKey;
204
+ const fn = source?.[key];
205
+ if (typeof fn === "function") {
206
+ target[targetKey] = fn.bind(source);
207
+ return true;
208
+ }
209
+ return false;
210
+ }
211
+ function setupRoomNotifications(transport, getSubscriptions) {
212
+ console.log("[Venus Rooms] Setting up room notification listeners");
213
+ return transport.onVenusMessage((message) => {
214
+ const subscriptions = getSubscriptions();
215
+ if (!subscriptions) {
216
+ return;
217
+ }
218
+ if (message.type === "H5_ROOM_DATA_UPDATED") {
219
+ const messageData = message.data;
220
+ const { roomId, roomData } = messageData;
221
+ if (!roomId) return;
222
+ const callbacks = subscriptions.data?.[roomId] || [];
223
+ const allEventsCallbacks = subscriptions.allEvents?.[roomId] || [];
224
+ console.log(`[Venus Rooms] \u{1F514} Room data updated for ${roomId}, notifying ${callbacks.length} callbacks`, roomData);
225
+ callbacks.forEach((callback) => {
226
+ try {
227
+ callback(roomData);
228
+ } catch (error) {
229
+ console.error("[Venus Rooms] Error in room data callback:", error);
230
+ throw error;
231
+ }
232
+ });
233
+ allEventsCallbacks.forEach((callback) => {
234
+ try {
235
+ callback({ type: message.type, ...messageData });
236
+ } catch (error) {
237
+ console.error("[Venus Rooms] Error in allEvents callback:", error);
238
+ throw error;
239
+ }
240
+ });
241
+ }
242
+ if (message.type === "H5_ROOM_MESSAGE_RECEIVED" || message.type === "H5_ROOM_MESSAGE_UPDATED" || message.type === "H5_ROOM_MESSAGE_DELETED") {
243
+ const messageData = message.data;
244
+ const { roomId } = messageData;
245
+ if (!roomId) return;
246
+ const callbacks = subscriptions.messages?.[roomId] || [];
247
+ const allEventsCallbacks = subscriptions.allEvents?.[roomId] || [];
248
+ console.log(`[Venus Rooms] \u{1F514} Room message event for ${roomId}, notifying ${callbacks.length} callbacks`);
249
+ callbacks.forEach((callback) => {
250
+ try {
251
+ callback(messageData);
252
+ } catch (error) {
253
+ console.error("[Venus Rooms] Error in room message callback:", error);
254
+ throw error;
255
+ }
256
+ });
257
+ allEventsCallbacks.forEach((callback) => {
258
+ try {
259
+ callback({ type: message.type, ...messageData });
260
+ } catch (error) {
261
+ console.error("[Venus Rooms] Error in allEvents callback:", error);
262
+ throw error;
263
+ }
264
+ });
265
+ }
266
+ if (message.type === "app:h5:proposedMoveValidationUpdated") {
267
+ const messageData = message.data;
268
+ const { roomId } = messageData;
269
+ if (!roomId) return;
270
+ const callbacks = subscriptions.gameEvents?.[roomId] || [];
271
+ const allEventsCallbacks = subscriptions.allEvents?.[roomId] || [];
272
+ console.log(`[Venus Rooms] \u{1F514} Proposed move validation updated for ${roomId}, notifying ${callbacks.length} callbacks`);
273
+ callbacks.forEach((callback) => {
274
+ try {
275
+ callback(messageData);
276
+ } catch (error) {
277
+ console.error("[Venus Rooms] Error in game event callback:", error);
278
+ throw error;
279
+ }
280
+ });
281
+ allEventsCallbacks.forEach((callback) => {
282
+ try {
283
+ callback({ type: message.type, ...messageData });
284
+ } catch (error) {
285
+ console.error("[Venus Rooms] Error in allEvents callback:", error);
286
+ throw error;
287
+ }
288
+ });
289
+ }
290
+ });
291
+ }
292
+ function initializeRoomsApi(venusApi, host) {
293
+ const roomsApi = host?.rooms;
294
+ if (!roomsApi) {
295
+ console.warn(
296
+ "[Venus SDK] Host did not provide a rooms implementation. Rooms API will be unavailable."
297
+ );
298
+ return;
299
+ }
300
+ const venus = venusApi;
301
+ const existingNamespace = venus.rooms || {};
302
+ const roomsNamespace = Object.assign({}, existingNamespace);
303
+ const namespaceBindings = [
304
+ ["create", "createRoom"],
305
+ ["joinOrCreate", "joinOrCreateRoom"],
306
+ ["joinByCode", "joinRoomByCode"],
307
+ ["list", "getUserRooms"],
308
+ ["subscribeToRoom", "subscribe"],
309
+ ["updateRoomData", "updateData"],
310
+ ["getRoomData", "getData"],
311
+ ["sendRoomMessage", "sendMessage"],
312
+ ["leaveRoom", "leave"],
313
+ ["startRoomGame", "startGame"],
314
+ ["proposeMove"],
315
+ ["validateMove"]
316
+ ];
317
+ namespaceBindings.forEach(([targetKey, sourceKey]) => {
318
+ bindMethod(roomsNamespace, targetKey, roomsApi, sourceKey);
319
+ });
320
+ venus.rooms = roomsNamespace;
321
+ }
322
+ var init_rooms = __esm({
323
+ "src/rooms/index.ts"() {
324
+ init_RoomsApi();
325
+ init_VenusRoom();
326
+ }
327
+ });
328
+
103
329
  // src/storage/MockStorageApi.ts
104
330
  function createMockStorageApi(storageType, appUrl) {
105
331
  const appIdentifier = appUrl ? generateAppIdentifier(appUrl) : null;
@@ -409,6 +635,190 @@ function initializeAds(venusApiInstance, host) {
409
635
  venusApiInstance.ads = host.ads;
410
636
  }
411
637
 
638
+ // src/venus-api/systems/theme.js
639
+ init_core();
640
+ var DEFAULT_TYPOGRAPHY = {
641
+ fontFamily: {
642
+ base: "Plus Jakarta Sans, Roboto, sans-serif",
643
+ heading: "Plus Jakarta Sans, Roboto, sans-serif",
644
+ mono: "monospace"
645
+ },
646
+ fontSize: {
647
+ "2xs": "10px",
648
+ xs: "12px",
649
+ sm: "14px",
650
+ md: "16px",
651
+ lg: "18px",
652
+ xl: "20px",
653
+ "2xl": "24px",
654
+ "3xl": "30px",
655
+ "4xl": "36px",
656
+ "5xl": "48px",
657
+ "6xl": "60px"
658
+ },
659
+ fontWeight: {
660
+ thin: "100",
661
+ extralight: "200",
662
+ light: "300",
663
+ regular: "400",
664
+ medium: "500",
665
+ semibold: "600",
666
+ bold: "700",
667
+ extrabold: "800",
668
+ black: "900",
669
+ extrablack: "950"
670
+ },
671
+ lineHeight: {
672
+ none: "1",
673
+ tight: "1.25",
674
+ snug: "1.375",
675
+ normal: "1.5",
676
+ relaxed: "1.625",
677
+ loose: "2"
678
+ }
679
+ };
680
+ var DEFAULT_THEME = {
681
+ background: {
682
+ default: "#131419",
683
+ // Dark background
684
+ muted: "#1b1d25",
685
+ // Mid-dark background
686
+ dark: "#0d0e11"
687
+ // Darker background
688
+ },
689
+ text: {
690
+ primary: "#ffffff",
691
+ // White
692
+ muted: "#808080",
693
+ // Gray
694
+ inverted: "#000000"
695
+ // Black
696
+ },
697
+ theme: {
698
+ primary: "#f6c833",
699
+ // Different yellow for testing (slightly lighter)
700
+ secondary: "#6366f1",
701
+ // Different secondary for testing (purple)
702
+ background: "#131419",
703
+ // Dark background
704
+ border: "#262626",
705
+ // Dark border
706
+ card: "#1b1d25",
707
+ // Dark card
708
+ "card-glass": "rgba(27, 29, 37, 0.8)"
709
+ // Translucent dark card
710
+ },
711
+ typography: DEFAULT_TYPOGRAPHY
712
+ };
713
+ function initializeTheme(venusApiInstance) {
714
+ if (!venusApiInstance._mock.theme) {
715
+ venusApiInstance._mock.theme = DEFAULT_THEME;
716
+ }
717
+ if (!venusApiInstance._mock.typography) {
718
+ venusApiInstance._mock.typography = DEFAULT_TYPOGRAPHY;
719
+ }
720
+ if (!venusApiInstance._mock.safeArea) {
721
+ venusApiInstance._mock.safeArea = { top: 0, bottom: 0, left: 0, right: 0 };
722
+ }
723
+ venusApiInstance.applyVenusThemeToCSS = function(theme) {
724
+ if (!theme) return;
725
+ const root = document.documentElement;
726
+ if (theme.background) {
727
+ if (theme.background.default)
728
+ root.style.setProperty("--color-background", theme.background.default);
729
+ if (theme.background.muted)
730
+ root.style.setProperty(
731
+ "--color-background-muted",
732
+ theme.background.muted
733
+ );
734
+ if (theme.background.dark)
735
+ root.style.setProperty(
736
+ "--color-background-dark",
737
+ theme.background.dark
738
+ );
739
+ }
740
+ if (theme.text) {
741
+ if (theme.text.primary)
742
+ root.style.setProperty("--color-text-primary", theme.text.primary);
743
+ if (theme.text.muted)
744
+ root.style.setProperty("--color-text-muted", theme.text.muted);
745
+ }
746
+ if (theme.theme) {
747
+ if (theme.theme.primary)
748
+ root.style.setProperty("--color-primary", theme.theme.primary);
749
+ if (theme.theme.secondary)
750
+ root.style.setProperty("--color-secondary", theme.theme.secondary);
751
+ if (theme.theme.border)
752
+ root.style.setProperty("--color-border", theme.theme.border);
753
+ }
754
+ if (theme.typography && theme.typography.fontFamily) {
755
+ if (theme.typography.fontFamily.base) {
756
+ root.style.setProperty(
757
+ "--font-family",
758
+ theme.typography.fontFamily.base
759
+ );
760
+ }
761
+ }
762
+ document.body.style.backgroundColor = root.style.getPropertyValue(
763
+ "--color-background-dark"
764
+ );
765
+ };
766
+ venusApiInstance.applyTheme = createProxiedMethod("applyTheme", function() {
767
+ let apiTheme = null;
768
+ apiTheme = this.config.theme;
769
+ if (apiTheme) {
770
+ this.applyVenusThemeToCSS(apiTheme);
771
+ this.colors = {
772
+ primary: apiTheme.theme?.primary || "#FF2877",
773
+ secondary: apiTheme.theme?.secondary || "#4755FF",
774
+ dark: apiTheme.background?.dark || "#0D0E11",
775
+ darkLight: apiTheme.background?.muted || "#1B1D25",
776
+ darkLighter: apiTheme.background?.default || "#23252F",
777
+ textPrimary: apiTheme.text?.primary || "#FFFFFF",
778
+ textMuted: apiTheme.text?.muted || "#808080",
779
+ border: apiTheme.theme?.border || "#262626"
780
+ };
781
+ } else {
782
+ this.colors = {
783
+ primary: "#FF2877",
784
+ secondary: "#4755FF",
785
+ dark: "#0D0E11",
786
+ darkLight: "#1B1D25",
787
+ darkLighter: "#23252F",
788
+ textPrimary: "#FFFFFF",
789
+ textMuted: "#808080",
790
+ border: "#262626"
791
+ };
792
+ }
793
+ this.log("Theme applied successfully");
794
+ });
795
+ venusApiInstance.applySafeArea = createProxiedMethod("applySafeArea", function() {
796
+ try {
797
+ const safeArea = this.config.ui.safeArea;
798
+ if (safeArea) {
799
+ this.log("Applying safe area insets: " + JSON.stringify(safeArea));
800
+ if (this.tapToStartScreen) {
801
+ this.tapToStartScreen.style.marginTop = `${safeArea.top}px`;
802
+ this.tapToStartScreen.style.marginBottom = `${safeArea.bottom}px`;
803
+ }
804
+ if (this.gameOverScreen) {
805
+ this.gameOverScreen.style.marginTop = `${safeArea.top}px`;
806
+ this.gameOverScreen.style.marginBottom = `${safeArea.bottom}px`;
807
+ }
808
+ if (this.maxScoreContainer) {
809
+ this.maxScoreContainer.style.marginTop = `${safeArea.top}px`;
810
+ this.maxScoreContainer.style.marginRight = `${safeArea.right}px`;
811
+ }
812
+ }
813
+ } catch (error) {
814
+ this.error("Error applying safe area: " + error.message);
815
+ console.error("Error applying safe area:", error);
816
+ }
817
+ });
818
+ venusApiInstance.DEFAULT_THEME = DEFAULT_THEME;
819
+ venusApiInstance.DEFAULT_TYPOGRAPHY = DEFAULT_TYPOGRAPHY;
820
+ }
821
+
412
822
  // src/popups/RpcPopupsApi.ts
413
823
  var RpcPopupsApi = class {
414
824
  constructor(rpcClient) {
@@ -561,8 +971,13 @@ var MockNotificationsApi = class {
561
971
  async cancelNotification(notificationId) {
562
972
  const venusApi = this.venusApi;
563
973
  if (isWebPlatform()) {
974
+ console.log(
975
+ "[Venus Mock] Cancel notification on web platform (simulated):",
976
+ notificationId
977
+ );
564
978
  return true;
565
979
  }
980
+ console.log("[Venus Mock] Cancel local notification:", notificationId);
566
981
  await createMockDelay(MOCK_DELAYS.short);
567
982
  if (venusApi._mock.scheduledNotifications && venusApi._mock.scheduledNotifications[notificationId]) {
568
983
  delete venusApi._mock.scheduledNotifications[notificationId];
@@ -572,8 +987,12 @@ var MockNotificationsApi = class {
572
987
  }
573
988
  async getAllScheduledLocalNotifications() {
574
989
  if (isWebPlatform()) {
990
+ console.log(
991
+ "[Venus Mock] Get notifications on web platform (returning empty list)"
992
+ );
575
993
  return [];
576
994
  }
995
+ console.log("[Venus Mock] Get all scheduled local notifications");
577
996
  await createMockDelay(MOCK_DELAYS.short);
578
997
  const venusApi = this.venusApi;
579
998
  const notifications = venusApi._mock.scheduledNotifications || {};
@@ -581,8 +1000,10 @@ var MockNotificationsApi = class {
581
1000
  }
582
1001
  async isLocalNotificationsEnabled() {
583
1002
  if (isWebPlatform()) {
1003
+ console.log("[Venus Mock] Notifications not available on web platform");
584
1004
  return false;
585
1005
  }
1006
+ console.log("[Venus Mock] Check if local notifications are enabled");
586
1007
  await createMockDelay(MOCK_DELAYS.short);
587
1008
  const venusApi = this.venusApi;
588
1009
  const isEnabled = venusApi._mock.notificationsEnabled !== false;
@@ -591,6 +1012,9 @@ var MockNotificationsApi = class {
591
1012
  async scheduleAsync(title, body, seconds, notificationId, options) {
592
1013
  const { priority = 50, groupId, payload } = options || {};
593
1014
  if (isWebPlatform()) {
1015
+ console.log(
1016
+ "[Venus Mock] Notifications not supported on web platform, simulating success"
1017
+ );
594
1018
  console.info(
595
1019
  "\u{1F514} [Venus Mock] Notification would be scheduled:",
596
1020
  title || "Untitled",
@@ -601,11 +1025,14 @@ var MockNotificationsApi = class {
601
1025
  const mockId = `mock-web-notification-${Date.now()}`;
602
1026
  return mockId;
603
1027
  }
1028
+ console.log("[Venus Mock] Schedule local notification:", { title, body, seconds, options });
604
1029
  const venusApi = this.venusApi;
605
1030
  if (!venusApi._mock.pendingRequests) {
1031
+ console.log("[Venus Mock] Initializing pendingRequests");
606
1032
  venusApi._mock.pendingRequests = {};
607
1033
  }
608
1034
  const requestId = Date.now().toString();
1035
+ console.log("[Venus Mock] Creating request with ID:", requestId);
609
1036
  return new Promise((resolve) => {
610
1037
  venusApi._mock.pendingRequests[requestId] = { resolve };
611
1038
  const id = notificationId || `mock-notification-${Date.now()}`;
@@ -627,8 +1054,13 @@ var MockNotificationsApi = class {
627
1054
  async setLocalNotificationsEnabled(enabled) {
628
1055
  const venusApi = this.venusApi;
629
1056
  if (isWebPlatform()) {
1057
+ console.log(
1058
+ "[Venus Mock] Set notifications enabled on web platform (simulated):",
1059
+ enabled
1060
+ );
630
1061
  return true;
631
1062
  }
1063
+ console.log("[Venus Mock] Set local notifications enabled:", enabled);
632
1064
  await createMockDelay(MOCK_DELAYS.short);
633
1065
  venusApi._mock.notificationsEnabled = enabled;
634
1066
  return enabled;
@@ -725,11 +1157,9 @@ function isPacificDaylightTime(date) {
725
1157
 
726
1158
  // src/time/HostTimeApi.ts
727
1159
  var HostTimeApi = class {
728
- constructor(rpcClient, venusApi) {
1160
+ constructor(rpcClient) {
729
1161
  __publicField(this, "rpcClient");
730
- __publicField(this, "venusApi");
731
1162
  this.rpcClient = rpcClient;
732
- this.venusApi = venusApi;
733
1163
  }
734
1164
  async requestTimeAsync() {
735
1165
  const response = await this.rpcClient.call(
@@ -739,7 +1169,13 @@ var HostTimeApi = class {
739
1169
  return response;
740
1170
  }
741
1171
  formatTime(timestamp, options) {
742
- const locale = this.venusApi.getLocale();
1172
+ let locale = "en-US";
1173
+ const windowVenus = window.venus;
1174
+ if (windowVenus._config.locale) {
1175
+ locale = windowVenus._config.locale;
1176
+ } else if (windowVenus._config.environment && windowVenus._config.environment.browserInfo && windowVenus._config.environment.browserInfo.language) {
1177
+ locale = windowVenus._config.environment.browserInfo.language;
1178
+ }
743
1179
  const date = new Date(timestamp);
744
1180
  const dateTimeOptions = {
745
1181
  dateStyle: options.dateStyle || "medium",
@@ -751,7 +1187,13 @@ var HostTimeApi = class {
751
1187
  }
752
1188
  formatNumber(value, options) {
753
1189
  try {
754
- const locale = this.venusApi.getLocale();
1190
+ let locale = "en-US";
1191
+ const windowVenus = window.venus;
1192
+ if (windowVenus._config.locale) {
1193
+ locale = windowVenus._config.locale;
1194
+ } else if (windowVenus._config.environment && windowVenus._config.environment.browserInfo && windowVenus._config.environment.browserInfo.language) {
1195
+ locale = windowVenus._config.environment.browserInfo.language;
1196
+ }
755
1197
  const numberOptions = {
756
1198
  style: options?.style || "decimal",
757
1199
  minimumFractionDigits: options?.minimumFractionDigits || 0,
@@ -815,17 +1257,18 @@ var MockTimeApi = class {
815
1257
  this.venusApi = venusApi;
816
1258
  }
817
1259
  formatNumber(value, options) {
818
- const locale = this.venusApi.getLocale();
1260
+ const locale = this.getLocale();
819
1261
  const numberOptions = {
820
1262
  style: options?.style || "decimal",
821
1263
  minimumFractionDigits: options?.minimumFractionDigits || 0,
822
1264
  maximumFractionDigits: options?.maximumFractionDigits || 2,
823
1265
  ...options
824
1266
  };
1267
+ console.log(`[Venus Mock] Formatting number ${value} with locale ${locale}`);
825
1268
  return value.toLocaleString(locale, numberOptions);
826
1269
  }
827
1270
  formatTime(timestamp, options) {
828
- const locale = this.venusApi.getLocale();
1271
+ const locale = this.getLocale();
829
1272
  const date = new Date(timestamp);
830
1273
  const dateTimeOptions = {
831
1274
  dateStyle: options.dateStyle || "medium",
@@ -833,9 +1276,13 @@ var MockTimeApi = class {
833
1276
  hour12: options.hour12 !== void 0 ? options.hour12 : true,
834
1277
  ...options
835
1278
  };
1279
+ console.log(
1280
+ `[Venus Mock] Formatting time ${timestamp} with locale ${locale}`
1281
+ );
836
1282
  return date.toLocaleString(locale, dateTimeOptions);
837
1283
  }
838
1284
  async getFutureTimeAsync(options) {
1285
+ console.log("[Venus Mock] Getting future time with options:", options);
839
1286
  const timeInfo = await this.requestTimeAsync();
840
1287
  const serverTime = new Date(timeInfo.serverTime);
841
1288
  const result = new Date(serverTime);
@@ -880,6 +1327,7 @@ var MockTimeApi = class {
880
1327
  return result.getTime();
881
1328
  }
882
1329
  async requestTimeAsync() {
1330
+ console.log("[Venus Mock] Requesting time");
883
1331
  await createMockDelay(MOCK_DELAYS.short);
884
1332
  const venusApi = this.venusApi;
885
1333
  const mockOffset = venusApi._mock.serverTimeOffset || 2500;
@@ -893,8 +1341,23 @@ var MockTimeApi = class {
893
1341
  formattedTime: new Date(localTime).toISOString(),
894
1342
  locale: venusApi._mock.user?.locale || "en-US"
895
1343
  };
1344
+ console.log("[Venus Mock] Time response:", {
1345
+ serverTime: new Date(timeInfo.serverTime).toISOString(),
1346
+ localTime: new Date(timeInfo.localTime).toISOString(),
1347
+ timezoneOffset: timeInfo.timezoneOffset
1348
+ });
896
1349
  return timeInfo;
897
1350
  }
1351
+ getLocale() {
1352
+ const venusApi = this.venusApi;
1353
+ let locale = "en-US";
1354
+ if (venusApi._mock.user && venusApi._mock.user.locale) {
1355
+ locale = venusApi._mock.user.locale;
1356
+ } else if (venusApi._mock.environment && venusApi._mock.environment.browserInfo.language) {
1357
+ locale = venusApi._mock.environment.browserInfo.language;
1358
+ }
1359
+ return locale;
1360
+ }
898
1361
  };
899
1362
 
900
1363
  // src/time/index.ts
@@ -929,7 +1392,7 @@ var MockAvatarApi = class {
929
1392
  async deleteAvatar() {
930
1393
  console.log(`[Venus Mock] Deleting avatar3d config`);
931
1394
  const venusApi = this._venusApi;
932
- const currentProfile = venusApi.getProfile();
1395
+ const currentProfile = venusApi.getCurrentProfile();
933
1396
  const profileId = currentProfile?.id || "default_profile";
934
1397
  localStorage.removeItem(`venus-mock-avatar3d-${profileId}`);
935
1398
  console.log(
@@ -944,7 +1407,7 @@ var MockAvatarApi = class {
944
1407
  console.log(`[Venus Mock] Loading shared avatar3d by ID: ${avatar3dId}`);
945
1408
  config = await this.selectAvatarConfig(avatar3dId, false);
946
1409
  } else {
947
- const currentProfile = venusApi.getProfile();
1410
+ const currentProfile = venusApi.getCurrentProfile();
948
1411
  const profileId = currentProfile?.id || "default_profile";
949
1412
  console.log(`[Venus Mock] Loading avatar3d for profile: ${profileId}`);
950
1413
  console.log(
@@ -961,7 +1424,7 @@ var MockAvatarApi = class {
961
1424
  async saveAvatar(config) {
962
1425
  console.log(`[Venus Mock] Saving avatar3d config:`, config);
963
1426
  const venusApi = this._venusApi;
964
- const currentProfile = venusApi.getProfile();
1427
+ const currentProfile = venusApi.getCurrentProfile();
965
1428
  const profileId = currentProfile?.id || "default_profile";
966
1429
  localStorage.setItem(
967
1430
  `venus-mock-avatar3d-${profileId}`,
@@ -1622,7 +2085,7 @@ var VenusAssetLoader = class {
1622
2085
  // Set the VenusAPI reference during initialization
1623
2086
  setVenusAPI(api) {
1624
2087
  this.venusAPI = api;
1625
- this.isWebView = typeof window !== "undefined" && typeof window.ReactNativeWebView !== "undefined";
2088
+ this.isWebView = !api.isWeb || !api.isWeb();
1626
2089
  }
1627
2090
  /**
1628
2091
  * Load any asset with automatic optimization
@@ -1743,11 +2206,14 @@ var VenusAssetLoader = class {
1743
2206
  }, 1e4);
1744
2207
  if (type === "image") {
1745
2208
  const img = new Image();
2209
+ console.log(`\u{1F5BC}\uFE0F [Asset Verification] Verifying image: ${url}`);
1746
2210
  img.onload = () => {
2211
+ console.log(`\u2705 [Asset Verification] Image verified successfully: ${url}`);
1747
2212
  clearTimeout(timeout);
1748
2213
  resolve();
1749
2214
  };
1750
2215
  img.onerror = (error) => {
2216
+ console.log(`\u274C [Asset Verification] Image verification failed: ${url}`, error);
1751
2217
  clearTimeout(timeout);
1752
2218
  reject(new Error("Failed to load image"));
1753
2219
  };
@@ -1799,6 +2265,7 @@ var VenusAssetLoader = class {
1799
2265
  const CDN_BASE_URL = "https://venus-static-01293ak.web.app/";
1800
2266
  const cleanUrl = url.startsWith("/") ? url.slice(1) : url;
1801
2267
  const fullUrl = CDN_BASE_URL + cleanUrl;
2268
+ console.log(`\u{1F310} [Asset Loader] Force remote CDN: ${url} -> ${fullUrl}`);
1802
2269
  return fullUrl;
1803
2270
  }
1804
2271
  if (this.venusAPI && this.venusAPI.isMock && this.venusAPI.isMock()) {
@@ -3509,105 +3976,47 @@ function initializeIap(venusApiInstance, host) {
3509
3976
  venusApiInstance.iap = host.iap;
3510
3977
  }
3511
3978
 
3512
- // src/leaderboard/utils.ts
3513
- var HASH_ALGORITHM_WEB_CRYPTO = "SHA-256";
3514
- async function computeScoreHash(score, duration, token, sealingNonce, sealingSecret) {
3515
- const payload = `score:${score}|duration:${duration}|token:${token}`;
3516
- const fullPayload = `${payload}|nonce:${sealingNonce}`;
3517
- const encoder = new TextEncoder();
3518
- const keyData = encoder.encode(sealingSecret);
3519
- const messageData = encoder.encode(fullPayload);
3520
- const cryptoKey = await crypto.subtle.importKey(
3521
- "raw",
3522
- keyData,
3523
- { name: "HMAC", hash: HASH_ALGORITHM_WEB_CRYPTO },
3524
- false,
3525
- ["sign"]
3526
- );
3527
- const signature = await crypto.subtle.sign("HMAC", cryptoKey, messageData);
3528
- return Array.from(new Uint8Array(signature)).map((b) => b.toString(16).padStart(2, "0")).join("");
3529
- }
3530
-
3531
3979
  // src/leaderboard/RpcLeaderboardApi.ts
3532
3980
  var RpcLeaderboardApi = class {
3533
3981
  constructor(rpcClient) {
3534
3982
  __publicField(this, "rpcClient");
3535
- /** Cache of score tokens for automatic hash computation */
3536
- __publicField(this, "tokenCache", /* @__PURE__ */ new Map());
3537
3983
  this.rpcClient = rpcClient;
3538
3984
  }
3539
- /**
3540
- * Create a score token for submitting a score.
3541
- * Token is cached for automatic hash computation if score sealing is enabled.
3542
- *
3543
- * @param mode - Optional game mode
3544
- * @returns Score token with sealing data if enabled
3545
- */
3546
- async createScoreToken(mode) {
3547
- const token = await this.rpcClient.call(
3548
- "H5_LEADERBOARD_CREATE_SCORE_TOKEN" /* H5_LEADERBOARD_CREATE_SCORE_TOKEN */,
3985
+ startRun(mode) {
3986
+ return this.rpcClient.call(
3987
+ "H5_LEADERBOARD_START_RUN" /* H5_LEADERBOARD_START_RUN */,
3549
3988
  mode ? { mode } : {}
3550
3989
  );
3551
- this.tokenCache.set(token.token, token);
3552
- return token;
3553
3990
  }
3554
- /**
3555
- * Submit a score to the leaderboard.
3556
- * Automatically computes hash if score sealing is enabled and token was created via createScoreToken().
3557
- *
3558
- * @param params - Score submission parameters
3559
- * @returns Submission result with acceptance status and rank
3560
- * @throws Error if token not found in cache
3561
- */
3562
- async submitScore(params) {
3563
- let hash;
3564
- if (params.token) {
3565
- const cachedToken = this.tokenCache.get(params.token);
3566
- if (!cachedToken) {
3567
- throw new Error(
3568
- "Invalid token: not found in cache. Did you call createScoreToken() first?"
3569
- );
3570
- }
3571
- if (cachedToken.sealingNonce && cachedToken.sealingSecret) {
3572
- hash = await computeScoreHash(
3573
- params.score,
3574
- params.duration,
3575
- params.token,
3576
- cachedToken.sealingNonce,
3577
- cachedToken.sealingSecret
3578
- );
3579
- }
3580
- this.tokenCache.delete(params.token);
3581
- }
3991
+ submitScore(sessionId, score, durationSec, options) {
3582
3992
  return this.rpcClient.call(
3583
3993
  "H5_LEADERBOARD_SUBMIT_SCORE" /* H5_LEADERBOARD_SUBMIT_SCORE */,
3584
3994
  {
3585
- token: params.token,
3586
- score: params.score,
3587
- duration: params.duration,
3588
- mode: params.mode,
3589
- telemetry: params.telemetry,
3590
- metadata: params.metadata,
3591
- hash
3592
- // undefined if no sealing, computed if sealing enabled
3995
+ sessionId,
3996
+ score,
3997
+ durationSec,
3998
+ mode: options?.mode,
3999
+ telemetry: options?.telemetry,
4000
+ metadata: options?.metadata,
4001
+ hash: options?.hash
3593
4002
  }
3594
4003
  );
3595
4004
  }
3596
- getPagedScores(options) {
4005
+ getLeaderboard(options) {
3597
4006
  return this.rpcClient.call(
3598
- "H5_LEADERBOARD_GET_PAGED_SCORES" /* H5_LEADERBOARD_GET_PAGED_SCORES */,
4007
+ "H5_LEADERBOARD_GET" /* H5_LEADERBOARD_GET */,
3599
4008
  options ?? {}
3600
4009
  );
3601
4010
  }
3602
- getMyRank(options) {
4011
+ getPlayerStats(options) {
3603
4012
  return this.rpcClient.call(
3604
- "H5_LEADERBOARD_GET_MY_RANK" /* H5_LEADERBOARD_GET_MY_RANK */,
4013
+ "H5_LEADERBOARD_GET_PLAYER_STATS" /* H5_LEADERBOARD_GET_PLAYER_STATS */,
3605
4014
  options ?? {}
3606
4015
  );
3607
4016
  }
3608
- getPodiumScores(options) {
4017
+ getLeaderboardHighlight(options) {
3609
4018
  return this.rpcClient.call(
3610
- "H5_LEADERBOARD_GET_PODIUM_SCORES" /* H5_LEADERBOARD_GET_PODIUM_SCORES */,
4019
+ "H5_LEADERBOARD_GET_HIGHLIGHT" /* H5_LEADERBOARD_GET_HIGHLIGHT */,
3611
4020
  options ?? {}
3612
4021
  );
3613
4022
  }
@@ -3616,31 +4025,17 @@ var RpcLeaderboardApi = class {
3616
4025
  // src/leaderboard/MockLeaderboardApi.ts
3617
4026
  var MockLeaderboardApi = class {
3618
4027
  constructor(options) {
3619
- __publicField(this, "tokens", /* @__PURE__ */ new Map());
3620
- /** Cache of score tokens for automatic hash computation */
3621
- __publicField(this, "tokenCache", /* @__PURE__ */ new Map());
4028
+ __publicField(this, "sessions", /* @__PURE__ */ new Map());
3622
4029
  __publicField(this, "entriesByMode", /* @__PURE__ */ new Map());
3623
- __publicField(this, "tokenCounter", 0);
3624
- __publicField(this, "enableScoreSealing", false);
3625
- __publicField(this, "scoreSealingSecret", "mock-leaderboard-secret-key");
3626
- if (options?.enableScoreSealing) {
3627
- this.enableScoreSealing = true;
3628
- }
3629
- if (options?.scoreSealingSecret) {
3630
- this.scoreSealingSecret = options.scoreSealingSecret;
4030
+ __publicField(this, "sessionCounter", 0);
4031
+ __publicField(this, "requiresHash", false);
4032
+ if (options?.requiresHash) {
4033
+ this.requiresHash = true;
3631
4034
  }
3632
4035
  }
3633
- /**
3634
- * Configure mock leaderboard settings
3635
- *
3636
- * @param options - Configuration options
3637
- */
3638
4036
  configure(options) {
3639
- if (typeof options.enableScoreSealing === "boolean") {
3640
- this.enableScoreSealing = options.enableScoreSealing;
3641
- }
3642
- if (options.scoreSealingSecret) {
3643
- this.scoreSealingSecret = options.scoreSealingSecret;
4037
+ if (typeof options.requiresHash === "boolean") {
4038
+ this.requiresHash = options.requiresHash;
3644
4039
  }
3645
4040
  }
3646
4041
  generateNonce() {
@@ -3657,149 +4052,83 @@ var MockLeaderboardApi = class {
3657
4052
  }
3658
4053
  return this.entriesByMode.get(key);
3659
4054
  }
3660
- /**
3661
- * Create a mock score token for testing.
3662
- * Token is cached for automatic hash computation if score sealing is enabled.
3663
- *
3664
- * @param mode - Optional game mode
3665
- * @returns Score token with sealing data if enabled
3666
- */
3667
- async createScoreToken(mode) {
3668
- const token = `mock_token_${++this.tokenCounter}`;
4055
+ async startRun(mode) {
4056
+ const sessionId = `mock_session_${++this.sessionCounter}`;
3669
4057
  const startTime = Date.now();
3670
4058
  const expiresAt = startTime + 36e5;
3671
4059
  const resolvedMode = mode || "default";
3672
- const sealingNonce = this.enableScoreSealing ? this.generateNonce() : null;
3673
- const sealingSecret = this.enableScoreSealing ? this.scoreSealingSecret : null;
3674
- this.tokens.set(token, {
3675
- id: token,
4060
+ const hashNonce = this.requiresHash ? this.generateNonce() : null;
4061
+ this.sessions.set(sessionId, {
4062
+ id: sessionId,
3676
4063
  expiresAt,
3677
4064
  mode: resolvedMode,
3678
- sealingNonce,
4065
+ hashNonce,
3679
4066
  used: false
3680
4067
  });
3681
- const result = {
3682
- token,
4068
+ return {
4069
+ sessionId,
3683
4070
  startTime,
3684
4071
  expiresAt,
3685
- sealingNonce,
3686
- sealingSecret,
4072
+ hashNonce,
3687
4073
  mode: resolvedMode
3688
4074
  };
3689
- this.tokenCache.set(token, result);
3690
- return result;
3691
4075
  }
3692
- /**
3693
- * Submit a mock score to the leaderboard.
3694
- * Automatically computes hash if score sealing is enabled and token was created via createScoreToken().
3695
- *
3696
- * @param params - Score submission parameters
3697
- * @returns Submission result with acceptance status and rank
3698
- * @throws Error if token not found in cache or validation fails
3699
- */
3700
- async submitScore(params) {
3701
- let hash;
3702
- if (params.token) {
3703
- const cachedToken = this.tokenCache.get(params.token);
3704
- if (!cachedToken) {
3705
- throw new Error(
3706
- "Invalid token: not found in cache. Did you call createScoreToken() first?"
3707
- );
3708
- }
3709
- if (cachedToken.sealingNonce && cachedToken.sealingSecret) {
3710
- hash = await computeScoreHash(
3711
- params.score,
3712
- params.duration,
3713
- params.token,
3714
- cachedToken.sealingNonce,
3715
- cachedToken.sealingSecret
3716
- );
3717
- }
3718
- }
3719
- if (!params.token) {
3720
- const mode = params.mode || "default";
3721
- const submittedAt2 = Date.now();
3722
- const entry2 = {
3723
- profileId: `mock_profile`,
3724
- username: "Mock Player",
3725
- avatarUrl: null,
3726
- score: params.score,
3727
- duration: params.duration,
3728
- submittedAt: submittedAt2,
3729
- token: "simple-mode",
3730
- rank: null,
3731
- zScore: null,
3732
- isAnomaly: false,
3733
- trustScore: 50,
3734
- metadata: params.metadata ?? null,
3735
- isSeed: false
3736
- };
3737
- const modeEntries2 = this.getEntriesForMode(mode);
3738
- modeEntries2.push(entry2);
3739
- modeEntries2.sort((a, b) => {
3740
- if (b.score !== a.score) return b.score - a.score;
3741
- return a.submittedAt - b.submittedAt;
3742
- });
3743
- modeEntries2.forEach((e, index) => {
3744
- modeEntries2[index] = { ...e, rank: index + 1 };
3745
- });
3746
- const inserted2 = modeEntries2.find((e) => e.submittedAt === submittedAt2);
3747
- return {
3748
- accepted: true,
3749
- rank: inserted2?.rank ?? null
3750
- };
3751
- }
3752
- const scoreToken = this.tokens.get(params.token);
3753
- if (!scoreToken) {
3754
- throw new Error("Invalid score token");
4076
+ async submitScore(sessionId, score, durationSec, options) {
4077
+ const session = this.sessions.get(sessionId);
4078
+ if (!session) {
4079
+ throw new Error("Invalid leaderboard session");
3755
4080
  }
3756
- if (scoreToken.expiresAt < Date.now()) {
3757
- throw new Error("Invalid or expired score token");
4081
+ if (session.expiresAt < Date.now()) {
4082
+ throw new Error("Invalid or expired leaderboard session");
3758
4083
  }
3759
- if (scoreToken.used) {
3760
- throw new Error("Score token already used");
4084
+ if (session.used) {
4085
+ throw new Error("Leaderboard session already used");
3761
4086
  }
3762
- if (params.mode && params.mode !== scoreToken.mode) {
3763
- throw new Error("Submission mode does not match token mode");
4087
+ if (options?.mode && options.mode !== session.mode) {
4088
+ throw new Error("Submission mode does not match session mode");
3764
4089
  }
3765
- if (scoreToken.sealingNonce && !hash) {
3766
- throw new Error("Score hash required when score sealing is enabled");
4090
+ if (session.hashNonce && !options?.hash) {
4091
+ throw new Error("Score hash is required for sealed leaderboard submissions");
3767
4092
  }
3768
4093
  const submittedAt = Date.now();
3769
4094
  const entry = {
3770
4095
  profileId: `mock_profile`,
3771
4096
  username: "Mock Player",
3772
4097
  avatarUrl: null,
3773
- score: params.score,
3774
- duration: params.duration,
4098
+ score,
4099
+ durationSec,
3775
4100
  submittedAt,
3776
- token: params.token,
4101
+ sessionId,
3777
4102
  rank: null,
3778
4103
  zScore: null,
3779
4104
  isAnomaly: false,
3780
4105
  trustScore: 50,
3781
- metadata: params.metadata ?? null,
4106
+ metadata: options?.metadata ?? null,
3782
4107
  isSeed: false
3783
4108
  };
3784
- const modeEntries = this.getEntriesForMode(scoreToken.mode);
4109
+ const modeEntries = this.getEntriesForMode(session.mode);
3785
4110
  modeEntries.push(entry);
3786
4111
  modeEntries.sort((a, b) => {
3787
- if (b.score !== a.score) return b.score - a.score;
4112
+ if (b.score !== a.score) {
4113
+ return b.score - a.score;
4114
+ }
3788
4115
  return a.submittedAt - b.submittedAt;
3789
4116
  });
3790
4117
  modeEntries.forEach((e, index) => {
3791
- modeEntries[index] = { ...e, rank: index + 1 };
4118
+ modeEntries[index] = {
4119
+ ...e,
4120
+ rank: index + 1
4121
+ };
3792
4122
  });
3793
- scoreToken.used = true;
3794
- scoreToken.sealingNonce = null;
3795
- this.tokenCache.delete(params.token);
3796
- const inserted = modeEntries.find((e) => e.token === params.token && e.submittedAt === submittedAt);
4123
+ session.used = true;
4124
+ session.hashNonce = null;
4125
+ const inserted = modeEntries.find((e) => e.sessionId === sessionId && e.submittedAt === submittedAt);
3797
4126
  return {
3798
4127
  accepted: true,
3799
4128
  rank: inserted?.rank ?? null
3800
4129
  };
3801
4130
  }
3802
- async getPagedScores(options) {
4131
+ async getLeaderboard(options) {
3803
4132
  const limit = options?.limit ?? 10;
3804
4133
  const mode = options?.mode ?? "default";
3805
4134
  const modeEntries = [...this.getEntriesForMode(mode)];
@@ -3815,7 +4144,7 @@ var MockLeaderboardApi = class {
3815
4144
  periodInstance: options?.period ?? "alltime"
3816
4145
  };
3817
4146
  }
3818
- async getMyRank(_options) {
4147
+ async getPlayerStats(_options) {
3819
4148
  const mode = _options?.mode ?? "default";
3820
4149
  const modeEntries = this.getEntriesForMode(mode);
3821
4150
  const playerEntry = modeEntries[0] ?? null;
@@ -3828,7 +4157,7 @@ var MockLeaderboardApi = class {
3828
4157
  periodInstance: _options?.period ?? "alltime"
3829
4158
  };
3830
4159
  }
3831
- async getPodiumScores(options) {
4160
+ async getLeaderboardHighlight(options) {
3832
4161
  const mode = options?.mode ?? "default";
3833
4162
  const modeEntries = [...this.getEntriesForMode(mode)];
3834
4163
  const topCount = Math.max(1, Math.min(options?.topCount ?? 3, 10));
@@ -3881,20 +4210,16 @@ function initializeLeaderboard(venusApiInstance, host) {
3881
4210
 
3882
4211
  // src/profile/HostProfileApi.ts
3883
4212
  var HostProfileApi = class {
3884
- constructor(venusApi) {
3885
- __publicField(this, "venusApi");
3886
- this.venusApi = venusApi;
3887
- }
3888
4213
  getCurrentProfile() {
3889
- const profile = this.venusApi._profileData;
4214
+ const profile = window.venus?.profile;
3890
4215
  if (!profile) {
3891
4216
  throw new Error(
3892
- "[Venus SDK] Profile not available. You must await VenusAPI.initializeAsync() before calling getProfile(). INIT_SDK has not completed."
4217
+ "[Venus SDK] Host profile handshake did not complete. Await VenusAPI.initializeAsync() so INIT_SDK can deliver the profile before calling profile APIs."
3893
4218
  );
3894
4219
  }
3895
4220
  if (!profile.id || !profile.username) {
3896
4221
  throw new Error(
3897
- "[Venus SDK] INIT_SDK returned an incomplete profile (missing id/username). The host must supply valid profile data."
4222
+ "[Venus SDK] INIT_SDK returned an incomplete profile (missing id/username). The host must supply real credentials before rooms APIs are used."
3898
4223
  );
3899
4224
  }
3900
4225
  return {
@@ -3908,10 +4233,6 @@ var HostProfileApi = class {
3908
4233
 
3909
4234
  // src/profile/MockProfileApi.ts
3910
4235
  var MockProfileApi = class {
3911
- constructor(venusApi) {
3912
- __publicField(this, "venusApi");
3913
- this.venusApi = venusApi;
3914
- }
3915
4236
  getCurrentProfile() {
3916
4237
  return {
3917
4238
  id: "mock_profile_123",
@@ -3924,272 +4245,60 @@ var MockProfileApi = class {
3924
4245
 
3925
4246
  // src/profile/index.ts
3926
4247
  function initializeProfile(venusApi, host) {
3927
- venusApi.getProfile = () => {
3928
- return host.profile.getCurrentProfile();
3929
- };
3930
4248
  venusApi.getCurrentProfile = () => {
3931
- console.warn(
3932
- "[Venus SDK] DEPRECATED: VenusAPI.getCurrentProfile() is deprecated. Use VenusAPI.getProfile() instead. See migration guide: https://docs.venus.com/migration/profile-api"
3933
- );
3934
4249
  return host.profile.getCurrentProfile();
3935
4250
  };
3936
4251
  }
3937
4252
 
3938
- // src/system/HostSystemApi.ts
3939
- var HostSystemApi = class {
3940
- constructor(deviceApi, environmentApi, venusApi) {
3941
- __publicField(this, "deviceApi");
3942
- __publicField(this, "environmentApi");
3943
- __publicField(this, "venusApi");
3944
- this.deviceApi = deviceApi;
3945
- this.environmentApi = environmentApi;
3946
- this.venusApi = venusApi;
3947
- }
3948
- getDevice() {
3949
- return this.deviceApi.getDevice();
4253
+ // src/cdn/HostCdnApi.ts
4254
+ var HostCdnApi = class {
4255
+ constructor(baseUrl) {
4256
+ __publicField(this, "baseUrl");
4257
+ this.baseUrl = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
3950
4258
  }
3951
- getEnvironment() {
3952
- return this.environmentApi.getEnvironment();
4259
+ async fetchBlob(path, options) {
4260
+ const controller = new AbortController();
4261
+ const timeoutId = setTimeout(
4262
+ () => controller.abort(),
4263
+ options?.timeout ?? 3e4
4264
+ );
4265
+ try {
4266
+ const url = this.resolveAssetUrl(path);
4267
+ const response = await fetch(url, {
4268
+ mode: "cors",
4269
+ credentials: "omit",
4270
+ headers: { Accept: "/*" },
4271
+ signal: controller.signal
4272
+ });
4273
+ clearTimeout(timeoutId);
4274
+ if (!response.ok) {
4275
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
4276
+ }
4277
+ return await response.blob();
4278
+ } catch (error) {
4279
+ clearTimeout(timeoutId);
4280
+ throw error;
4281
+ }
3953
4282
  }
3954
- getSafeArea() {
3955
- const safeArea = this.venusApi._safeAreaData;
3956
- if (!safeArea) {
4283
+ async fetchFromCdn(url, request) {
4284
+ const response = await fetch(url, {
4285
+ method: "GET",
4286
+ headers: {
4287
+ Accept: "application/json, text/plain, */*",
4288
+ "Content-Type": "application/json"
4289
+ },
4290
+ mode: "cors",
4291
+ cache: "no-cache"
4292
+ });
4293
+ if (!response.ok) {
3957
4294
  throw new Error(
3958
- "[Venus SDK] getSafeArea() called before initialization. Call VenusAPI.initializeAsync() first."
4295
+ `CDN fetch failed: \${response.status} \${response.statusText}`
3959
4296
  );
3960
4297
  }
3961
- return { ...safeArea };
3962
- }
3963
- isMobile() {
3964
- const environment = this.environmentApi.getEnvironment();
3965
- if (environment.platform === "ios" || environment.platform === "android") {
3966
- return true;
3967
- }
3968
- if (environment.browserInfo) {
3969
- return environment.browserInfo.isMobile;
3970
- }
3971
- return true;
4298
+ return response;
3972
4299
  }
3973
- isWeb() {
3974
- const environment = this.environmentApi.getEnvironment();
3975
- if (environment.platform === "web") {
3976
- return true;
3977
- }
3978
- if (environment.browserInfo && !environment.browserInfo.isMobile) {
3979
- return true;
3980
- }
3981
- return false;
3982
- }
3983
- };
3984
-
3985
- // src/system/MockSystemApi.ts
3986
- var MockSystemApi = class {
3987
- constructor(deviceApi, environmentApi, venusApi) {
3988
- __publicField(this, "deviceApi");
3989
- __publicField(this, "environmentApi");
3990
- __publicField(this, "venusApi");
3991
- this.deviceApi = deviceApi;
3992
- this.environmentApi = environmentApi;
3993
- this.venusApi = venusApi;
3994
- }
3995
- getDevice() {
3996
- return this.deviceApi.getDevice();
3997
- }
3998
- getEnvironment() {
3999
- return this.environmentApi.getEnvironment();
4000
- }
4001
- getSafeArea() {
4002
- const safeArea = this.venusApi._safeAreaData;
4003
- if (!safeArea) {
4004
- return {
4005
- top: 0,
4006
- right: 0,
4007
- bottom: 34,
4008
- left: 0
4009
- };
4010
- }
4011
- return { ...safeArea };
4012
- }
4013
- isMobile() {
4014
- const environment = this.environmentApi.getEnvironment();
4015
- if (environment.platform === "ios" || environment.platform === "android") {
4016
- return true;
4017
- }
4018
- if (environment.browserInfo) {
4019
- return environment.browserInfo.isMobile;
4020
- }
4021
- return true;
4022
- }
4023
- isWeb() {
4024
- const environment = this.environmentApi.getEnvironment();
4025
- if (environment.platform === "web") {
4026
- return true;
4027
- }
4028
- if (environment.browserInfo && !environment.browserInfo.isMobile) {
4029
- return true;
4030
- }
4031
- return false;
4032
- }
4033
- };
4034
-
4035
- // src/system/index.ts
4036
- function initializeSystem(venusApi, host) {
4037
- venusApi.system = host.system;
4038
- venusApi.isMobile = () => {
4039
- console.warn(
4040
- "[Venus SDK] DEPRECATED: VenusAPI.isMobile() is deprecated. Use VenusAPI.system.isMobile() instead."
4041
- );
4042
- return host.system.isMobile();
4043
- };
4044
- venusApi.isWeb = () => {
4045
- console.warn(
4046
- "[Venus SDK] DEPRECATED: VenusAPI.isWeb() is deprecated. Use VenusAPI.system.isWeb() instead."
4047
- );
4048
- return host.system.isWeb();
4049
- };
4050
- }
4051
-
4052
- // src/device/HostDeviceApi.ts
4053
- var HostDeviceApi = class {
4054
- constructor(venusApi) {
4055
- __publicField(this, "venusApi");
4056
- this.venusApi = venusApi;
4057
- }
4058
- getDevice() {
4059
- const device = this.venusApi._deviceData;
4060
- if (!device) {
4061
- throw new Error(
4062
- "[Venus SDK] Device info not available. You must await VenusAPI.initializeAsync() before calling getDevice(). INIT_SDK has not completed."
4063
- );
4064
- }
4065
- return device;
4066
- }
4067
- };
4068
-
4069
- // src/device/MockDeviceApi.ts
4070
- var MockDeviceApi = class {
4071
- constructor(venusApi) {
4072
- __publicField(this, "venusApi");
4073
- this.venusApi = venusApi;
4074
- }
4075
- getDevice() {
4076
- const width = typeof window !== "undefined" ? window.innerWidth : 400;
4077
- const height = typeof window !== "undefined" ? window.innerHeight : 800;
4078
- return {
4079
- screenSize: { width, height },
4080
- viewportSize: {
4081
- width: width - 20,
4082
- // account for safe area
4083
- height: height - 20
4084
- },
4085
- orientation: width > height ? "landscape" : "portrait",
4086
- pixelRatio: typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1,
4087
- fontScale: 1,
4088
- deviceType: width > 768 ? "tablet" : "phone",
4089
- hapticsEnabled: false,
4090
- haptics: { supported: false, enabled: false }
4091
- };
4092
- }
4093
- };
4094
-
4095
- // src/environment/HostEnvironmentApi.ts
4096
- var HostEnvironmentApi = class {
4097
- constructor(venusApi) {
4098
- __publicField(this, "venusApi");
4099
- this.venusApi = venusApi;
4100
- }
4101
- getEnvironment() {
4102
- const environment = this.venusApi._environmentData;
4103
- if (!environment) {
4104
- throw new Error(
4105
- "[Venus SDK] Environment info not available. You must await VenusAPI.initializeAsync() before calling getEnvironment(). INIT_SDK has not completed."
4106
- );
4107
- }
4108
- return environment;
4109
- }
4110
- };
4111
-
4112
- // src/environment/MockEnvironmentApi.ts
4113
- var MockEnvironmentApi = class {
4114
- constructor(venusApi) {
4115
- __publicField(this, "venusApi");
4116
- this.venusApi = venusApi;
4117
- }
4118
- getEnvironment() {
4119
- const getBrowser = () => {
4120
- if (typeof navigator === "undefined") return "unknown";
4121
- const userAgent = navigator.userAgent;
4122
- if (/chrome|chromium|crios/i.test(userAgent)) return "chrome";
4123
- if (/firefox|fxios/i.test(userAgent)) return "firefox";
4124
- if (/safari/i.test(userAgent)) return "safari";
4125
- if (/edg/i.test(userAgent)) return "edge";
4126
- if (/opera|opr/i.test(userAgent)) return "opera";
4127
- return "unknown";
4128
- };
4129
- return {
4130
- isDevelopment: true,
4131
- platform: "web",
4132
- platformVersion: "mock-1.0",
4133
- browserInfo: {
4134
- browser: getBrowser(),
4135
- userAgent: typeof navigator !== "undefined" ? navigator.userAgent : "mock-agent",
4136
- isMobile: typeof navigator !== "undefined" ? /Mobi|Android/i.test(navigator.userAgent) : false,
4137
- isTablet: typeof navigator !== "undefined" ? /iPad|Tablet|Pad/i.test(navigator.userAgent) : false,
4138
- language: typeof navigator !== "undefined" ? navigator.language || "en-US" : "en-US"
4139
- }
4140
- };
4141
- }
4142
- };
4143
-
4144
- // src/cdn/HostCdnApi.ts
4145
- var HostCdnApi = class {
4146
- constructor(baseUrl) {
4147
- __publicField(this, "baseUrl");
4148
- this.baseUrl = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
4149
- }
4150
- async fetchBlob(path, options) {
4151
- const controller = new AbortController();
4152
- const timeoutId = setTimeout(
4153
- () => controller.abort(),
4154
- options?.timeout ?? 3e4
4155
- );
4156
- try {
4157
- const url = this.resolveAssetUrl(path);
4158
- const response = await fetch(url, {
4159
- mode: "cors",
4160
- credentials: "omit",
4161
- headers: { Accept: "/*" },
4162
- signal: controller.signal
4163
- });
4164
- clearTimeout(timeoutId);
4165
- if (!response.ok) {
4166
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
4167
- }
4168
- return await response.blob();
4169
- } catch (error) {
4170
- clearTimeout(timeoutId);
4171
- throw error;
4172
- }
4173
- }
4174
- async fetchFromCdn(url, request) {
4175
- const response = await fetch(url, {
4176
- method: "GET",
4177
- headers: {
4178
- Accept: "application/json, text/plain, */*",
4179
- "Content-Type": "application/json"
4180
- },
4181
- mode: "cors",
4182
- cache: "no-cache"
4183
- });
4184
- if (!response.ok) {
4185
- throw new Error(
4186
- `CDN fetch failed: \${response.status} \${response.statusText}`
4187
- );
4188
- }
4189
- return response;
4190
- }
4191
- getAssetCdnBaseUrl() {
4192
- return this.baseUrl;
4300
+ getAssetCdnBaseUrl() {
4301
+ return this.baseUrl;
4193
4302
  }
4194
4303
  resolveAssetUrl(subPath) {
4195
4304
  const cleanSubPath = subPath.startsWith("/") ? subPath.slice(1) : subPath;
@@ -4213,15 +4322,9 @@ var HostCdnApi = class {
4213
4322
 
4214
4323
  // src/cdn/MockCdnApi.ts
4215
4324
  var MockCdnApi = class {
4216
- constructor(venusApi) {
4217
- __publicField(this, "venusApi");
4218
- this.venusApi = venusApi;
4219
- }
4220
- get baseUrl() {
4221
- return this.venusApi._mock?.cdnBaseUrl ?? "https://venus-static-01293ak.web.app/";
4222
- }
4223
- get forceRemoteCdn() {
4224
- return this.venusApi._mock?.cdnForceRemote ?? false;
4325
+ constructor() {
4326
+ __publicField(this, "baseUrl");
4327
+ this.baseUrl = "https://venus-static-01293ak.web.app/";
4225
4328
  }
4226
4329
  async fetchBlob(path, options) {
4227
4330
  const controller = new AbortController();
@@ -4258,10 +4361,6 @@ var MockCdnApi = class {
4258
4361
  return subPath;
4259
4362
  }
4260
4363
  const cleanSubPath = subPath.startsWith("/") ? subPath.slice(1) : subPath;
4261
- const isLocalhost = typeof window !== "undefined" && (window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1");
4262
- if (isLocalhost && !this.forceRemoteCdn) {
4263
- return `/${cleanSubPath}`;
4264
- }
4265
4364
  const pathParts = cleanSubPath.split("/");
4266
4365
  const encodedParts = pathParts.map((part, index) => {
4267
4366
  return index === pathParts.length - 1 ? encodeURIComponent(part) : part;
@@ -4383,6 +4482,96 @@ function initializeCdn(venusApi, host) {
4383
4482
  venusApi.cdn = host.cdn;
4384
4483
  }
4385
4484
 
4485
+ // src/post/MockPostApi.ts
4486
+ init_core();
4487
+ var MockPostApi = class {
4488
+ constructor(venusApi) {
4489
+ __publicField(this, "venusApi");
4490
+ this.venusApi = venusApi;
4491
+ }
4492
+ async getPostInfo() {
4493
+ const venusApi = this.venusApi;
4494
+ await createMockDelay(MOCK_DELAYS.short);
4495
+ return venusApi._mock.currentPostInteractions;
4496
+ }
4497
+ async openCommentsAsync() {
4498
+ await createMockDelay(MOCK_DELAYS.short);
4499
+ return {
4500
+ opened: true,
4501
+ commentsCount: 0
4502
+ };
4503
+ }
4504
+ async toggleFollowAsync() {
4505
+ const venusApi = this.venusApi;
4506
+ console.log("[Venus Mock] *Toggling follow status");
4507
+ await createMockDelay(MOCK_DELAYS.short);
4508
+ venusApi._mock.currentPostInteractions.isFollowing = !venusApi._mock.currentPostInteractions.isFollowing;
4509
+ const isFollowing = venusApi._mock.currentPostInteractions.isFollowing;
4510
+ return {
4511
+ isFollowing,
4512
+ action: isFollowing ? "followed" : "unfollowed"
4513
+ };
4514
+ }
4515
+ async toggleLikeAsync() {
4516
+ const venusApi = this.venusApi;
4517
+ await createMockDelay(MOCK_DELAYS.short);
4518
+ venusApi._mock.currentPostInteractions.isLiked = !venusApi._mock.currentPostInteractions.isLiked;
4519
+ const isLiked = venusApi._mock.currentPostInteractions.isLiked;
4520
+ if (isLiked) {
4521
+ venusApi._mock.currentPostInteractions.likesCount++;
4522
+ } else {
4523
+ venusApi._mock.currentPostInteractions.likesCount = Math.max(
4524
+ 0,
4525
+ venusApi._mock.currentPostInteractions.likesCount - 1
4526
+ );
4527
+ }
4528
+ return {
4529
+ isLiked,
4530
+ likesCount: venusApi._mock.currentPostInteractions.likesCount,
4531
+ action: isLiked ? "liked" : "unliked"
4532
+ };
4533
+ }
4534
+ };
4535
+
4536
+ // src/post/RpcPostApi.ts
4537
+ var RpcPostApi = class {
4538
+ constructor(rpcClient) {
4539
+ __publicField(this, "rpcClient");
4540
+ this.rpcClient = rpcClient;
4541
+ }
4542
+ getPostInfo() {
4543
+ return this.rpcClient.call("H5_GET_POST_INTERACTIONS" /* GET_POST_INTERACTIONS */, {});
4544
+ }
4545
+ openCommentsAsync() {
4546
+ return this.rpcClient.call("H5_OPEN_COMMENTS" /* OPEN_COMMENTS */, {});
4547
+ }
4548
+ toggleFollowAsync() {
4549
+ return this.rpcClient.call(
4550
+ "H5_TOGGLE_FOLLOW" /* TOGGLE_FOLLOW */,
4551
+ {}
4552
+ );
4553
+ }
4554
+ toggleLikeAsync() {
4555
+ return this.rpcClient.call("H5_TOGGLE_LIKE" /* TOGGLE_LIKE */, {});
4556
+ }
4557
+ };
4558
+
4559
+ // src/post/index.ts
4560
+ function initializePost(venusApi, host) {
4561
+ venusApi.getPostInteractionsAsync = () => {
4562
+ return host.post.getPostInfo();
4563
+ };
4564
+ venusApi.toggleFollowAsync = () => {
4565
+ return host.post.toggleFollowAsync();
4566
+ };
4567
+ venusApi.toggleLikeAsync = () => {
4568
+ return host.post.toggleLikeAsync();
4569
+ };
4570
+ venusApi.openCommentsAsync = async () => {
4571
+ await host.post.openCommentsAsync();
4572
+ };
4573
+ }
4574
+
4386
4575
  // src/haptics/RpcHapticsApi.ts
4387
4576
  var RpcHapticsApi = class {
4388
4577
  constructor(rpcClient) {
@@ -4573,426 +4762,871 @@ function initializeLifecycleApi(venusApi, host) {
4573
4762
  venusApi.lifecycles = host.lifecycle;
4574
4763
  }
4575
4764
 
4576
- // src/rooms/VenusRoom.ts
4577
- var VenusRoom = class {
4578
- constructor(roomData) {
4579
- __publicField(this, "id");
4580
- __publicField(this, "name");
4581
- __publicField(this, "players");
4582
- __publicField(this, "maxPlayers");
4583
- __publicField(this, "gameType");
4584
- __publicField(this, "appId");
4585
- __publicField(this, "type");
4586
- __publicField(this, "createdBy");
4587
- __publicField(this, "createdAt");
4588
- __publicField(this, "updatedAt");
4589
- __publicField(this, "isPrivate");
4590
- __publicField(this, "status");
4591
- __publicField(this, "customMetadata");
4592
- __publicField(this, "admins");
4593
- __publicField(this, "roomCode");
4594
- __publicField(this, "description");
4595
- __publicField(this, "data");
4596
- __publicField(this, "version");
4597
- this.id = roomData.id;
4598
- this.name = roomData.name;
4599
- this.players = Array.isArray(roomData.currentPlayers) ? [...roomData.currentPlayers] : [];
4600
- this.maxPlayers = roomData.maxPlayers;
4601
- this.gameType = roomData.gameType;
4602
- this.appId = roomData.appId;
4603
- this.type = roomData.type;
4604
- this.createdBy = roomData.createdBy;
4605
- this.createdAt = roomData.createdAt;
4606
- this.updatedAt = roomData.updatedAt;
4607
- this.isPrivate = roomData.isPrivate;
4608
- this.status = roomData.status;
4609
- this.customMetadata = roomData.customMetadata || {};
4610
- this.admins = Array.isArray(roomData.admins) ? [...roomData.admins] : [];
4611
- this.roomCode = roomData.roomCode;
4612
- this.description = roomData.description;
4613
- this.data = roomData.data || {};
4614
- this.version = roomData.version;
4615
- }
4616
- };
4617
-
4618
- // src/rooms/setupRoomNotifications.ts
4619
- function invokeCallbacks(callbacks, event, context) {
4620
- callbacks.forEach((callback) => {
4621
- try {
4622
- callback(event);
4623
- } catch (error) {
4624
- console.error(`[Venus SDK] Error in ${context} callback:`, error);
4625
- throw error;
4626
- }
4627
- });
4628
- }
4629
- function setupRoomNotifications(transport, getSubscriptions) {
4630
- return transport.onVenusMessage((message) => {
4631
- const subscriptions = getSubscriptions();
4632
- if (!subscriptions) {
4633
- return;
4634
- }
4635
- if (message.type === "H5_ROOM_DATA_UPDATED") {
4636
- const messageData = message.data;
4637
- const { roomId, roomData } = messageData;
4638
- if (!roomId) return;
4639
- const callbacks = subscriptions.data[roomId] || [];
4640
- const event = {
4641
- type: "H5_ROOM_DATA_UPDATED",
4642
- roomId,
4643
- roomData,
4644
- timestamp: messageData.timestamp
4645
- };
4646
- invokeCallbacks(callbacks, event, "room data");
4647
- }
4648
- if (message.type === "H5_ROOM_MESSAGE_RECEIVED" || message.type === "H5_ROOM_MESSAGE_UPDATED" || message.type === "H5_ROOM_MESSAGE_DELETED") {
4649
- const messageData = message.data;
4650
- const { roomId } = messageData;
4651
- if (!roomId) return;
4652
- const callbacks = subscriptions.messages[roomId] || [];
4653
- const event = {
4654
- type: message.type,
4655
- roomId,
4656
- message: messageData.message,
4657
- timestamp: messageData.timestamp
4658
- };
4659
- invokeCallbacks(callbacks, event, "room message");
4660
- }
4661
- if (message.type === "app:h5:proposedMoveValidationUpdated") {
4662
- const messageData = message.data;
4663
- const { roomId } = messageData;
4664
- if (!roomId) return;
4665
- const callbacks = subscriptions.gameEvents[roomId] || [];
4666
- const event = {
4667
- type: "app:h5:proposedMoveValidationUpdated",
4668
- roomId,
4669
- proposedMoveData: messageData.proposedMoveData,
4670
- proposedMoveId: messageData.proposedMoveId,
4671
- changeType: messageData.changeType,
4672
- timestamp: messageData.timestamp
4673
- };
4674
- invokeCallbacks(callbacks, event, "game event");
4765
+ // src/simulation/utils.ts
4766
+ function sumContributions(contributions) {
4767
+ const totals = {};
4768
+ for (const profileId in contributions) {
4769
+ for (const entityId in contributions[profileId]) {
4770
+ const amount = contributions[profileId][entityId] || 0;
4771
+ totals[entityId] = (totals[entityId] || 0) + amount;
4675
4772
  }
4676
- });
4773
+ }
4774
+ return totals;
4677
4775
  }
4678
4776
 
4679
- // src/rooms/RpcRoomsApi.ts
4680
- var RpcRoomsApi = class {
4777
+ // src/simulation/RpcSimulationApi.ts
4778
+ var RpcSimulationApi = class {
4681
4779
  constructor(rpcClient) {
4682
4780
  __publicField(this, "rpcClient");
4683
- __publicField(this, "subscriptions");
4781
+ __publicField(this, "_simulationConfig", null);
4684
4782
  this.rpcClient = rpcClient;
4685
- this.subscriptions = {
4686
- data: {},
4687
- messages: {},
4688
- gameEvents: {}
4689
- };
4690
4783
  }
4691
- /**
4692
- * Get the subscription state for external access (used by setupRoomNotifications)
4693
- */
4694
- getSubscriptions() {
4695
- return this.subscriptions;
4784
+ async validateSlotAssignmentAsync(containerId, slotId, itemId) {
4785
+ return this.rpcClient.call(
4786
+ "H5_SIMULATION_VALIDATE_ASSIGNMENT" /* H5_SIMULATION_VALIDATE_ASSIGNMENT */,
4787
+ {
4788
+ containerId,
4789
+ slotId,
4790
+ itemId
4791
+ }
4792
+ );
4696
4793
  }
4697
- /**
4698
- * Set up room notification routing from the transport
4699
- */
4700
- setupNotifications(transport) {
4701
- setupRoomNotifications(transport, () => this.getSubscriptions());
4794
+ sumContributions(contributions) {
4795
+ return sumContributions(contributions);
4796
+ }
4797
+ executeBatchOperationsAsync(operations, validateOnly) {
4798
+ return this.rpcClient.call("H5_SIMULATION_BATCH_OPERATIONS" /* H5_SIMULATION_BATCH_OPERATIONS */, {
4799
+ operations,
4800
+ validateOnly
4801
+ });
4702
4802
  }
4703
- async createRoomAsync(options) {
4803
+ async getAvailableItemsAsync(containerId, slotId) {
4704
4804
  const response = await this.rpcClient.call(
4705
- "H5_ROOM_CREATE" /* H5_ROOM_CREATE */,
4805
+ "H5_SIMULATION_GET_AVAILABLE_ITEMS" /* H5_SIMULATION_GET_AVAILABLE_ITEMS */,
4706
4806
  {
4707
- options
4807
+ containerId,
4808
+ slotId
4708
4809
  }
4709
4810
  );
4710
- if (response.success === false) {
4711
- const errorMessage = typeof response.error === "string" ? response.error : "Failed to create room";
4712
- throw new Error(errorMessage);
4713
- }
4714
- const room = new VenusRoom(response.roomData);
4715
- return room;
4811
+ return response.availableItems || [];
4716
4812
  }
4717
- async joinOrCreateRoomAsync(options) {
4718
- const response = await this.rpcClient.call(
4719
- "H5_ROOM_JOIN_OR_CREATE" /* H5_ROOM_JOIN_OR_CREATE */,
4813
+ calculatePowerPreviewAsync(containerId, slotId, candidateItemId) {
4814
+ return this.rpcClient.call(
4815
+ "H5_SIMULATION_CALCULATE_POWER_PREVIEW" /* H5_SIMULATION_CALCULATE_POWER_PREVIEW */,
4720
4816
  {
4721
- options
4817
+ containerId,
4818
+ slotId,
4819
+ candidateItemId
4722
4820
  }
4723
4821
  );
4724
- if (response.success === false) {
4725
- const errorMessage = typeof response.error === "string" ? response.error : "Failed to join or create room";
4726
- throw new Error(errorMessage);
4727
- }
4728
- const room = new VenusRoom(response.value.roomData);
4729
- return {
4730
- action: response.value.action,
4731
- room,
4732
- playersJoined: response.value.playersJoined
4733
- };
4734
4822
  }
4735
- async joinRoomByCodeAsync(roomCode) {
4823
+ assignItemToSlotAsync(containerId, slotId, itemId) {
4824
+ return this.rpcClient.call("H5_SIMULATION_ASSIGN_ITEM" /* H5_SIMULATION_ASSIGN_ITEM */, {
4825
+ containerId,
4826
+ slotId,
4827
+ itemId
4828
+ });
4829
+ }
4830
+ removeItemFromSlotAsync(containerId, slotId) {
4831
+ return this.rpcClient.call("H5_SIMULATION_REMOVE_ITEM" /* H5_SIMULATION_REMOVE_ITEM */, {
4832
+ containerId,
4833
+ slotId
4834
+ });
4835
+ }
4836
+ async getSlotContainersAsync() {
4736
4837
  const response = await this.rpcClient.call(
4737
- "H5_ROOM_JOIN_BY_CODE" /* H5_ROOM_JOIN_BY_CODE */,
4838
+ "H5_SIMULATION_GET_CONTAINERS" /* H5_SIMULATION_GET_CONTAINERS */,
4839
+ {}
4840
+ );
4841
+ return response.containers || [];
4842
+ }
4843
+ async getSlotAssignmentsAsync(containerId) {
4844
+ const response = await this.rpcClient.call(
4845
+ "H5_SIMULATION_GET_ASSIGNMENTS" /* H5_SIMULATION_GET_ASSIGNMENTS */,
4738
4846
  {
4739
- roomCode
4847
+ containerId
4740
4848
  }
4741
4849
  );
4742
- if (response?.success === false) {
4743
- const errorMessage = typeof response.error === "string" ? response.error : "Failed to join room by code";
4744
- throw new Error(errorMessage);
4745
- }
4746
- const room = new VenusRoom(response.roomData);
4747
- return room;
4850
+ return Array.isArray(response) ? response : response.assignments || [];
4748
4851
  }
4749
- // Get user's rooms with optional filtering
4750
- async getUserRoomsAsync(options = {}) {
4852
+ async getStateAsync(roomId) {
4751
4853
  const response = await this.rpcClient.call(
4752
- "H5_ROOM_GET_USER_ROOMS" /* H5_ROOM_GET_USER_ROOMS */,
4854
+ "H5_SIMULATION_GET_STATE" /* H5_SIMULATION_GET_STATE */,
4753
4855
  {
4754
- includeArchived: options.includeArchived ?? false
4856
+ roomId
4755
4857
  }
4756
4858
  );
4757
- if (response?.success === false) {
4758
- const errorMessage = typeof response.error === "string" ? response.error : "Failed to get user rooms";
4759
- throw new Error(errorMessage);
4859
+ console.log("[Venus SDK] getStateAsync", response);
4860
+ if (response.configuration) {
4861
+ this._simulationConfig = response.configuration;
4760
4862
  }
4761
- const venusRooms = [];
4762
- for (const roomData of response.rooms) {
4763
- if (!roomData.id) {
4764
- console.warn("[Venus SDK] getUserRooms: Skipping room with missing ID:", roomData);
4765
- continue;
4766
- }
4767
- try {
4768
- const venusRoom = new VenusRoom(roomData);
4769
- venusRooms.push(venusRoom);
4770
- } catch (error) {
4771
- console.warn(
4772
- "[Venus SDK] getUserRooms: Failed to create VenusRoom object:",
4773
- error,
4774
- roomData
4775
- );
4776
- }
4863
+ return response;
4864
+ }
4865
+ async getConfigAsync(roomId) {
4866
+ if (this._simulationConfig) {
4867
+ return this._simulationConfig;
4777
4868
  }
4778
- return venusRooms;
4869
+ const config = await this.rpcClient.call(
4870
+ "H5_SIMULATION_GET_CONFIG" /* H5_SIMULATION_GET_CONFIG */,
4871
+ {}
4872
+ );
4873
+ console.log("[Venus SDK] getConfigAsync", config);
4874
+ if (config) {
4875
+ this._simulationConfig = config;
4876
+ return config;
4877
+ }
4878
+ throw new Error("No simulation configuration available");
4779
4879
  }
4780
- async updateRoomDataAsync(room, updates, options = {}) {
4781
- const response = await this.rpcClient.call(
4782
- "H5_ROOM_UPDATE_DATA" /* H5_ROOM_UPDATE_DATA */,
4880
+ executeRecipeAsync(recipeId, inputs, options) {
4881
+ return this.rpcClient.call("H5_SIMULATION_EXECUTE_RECIPE" /* H5_SIMULATION_EXECUTE_RECIPE */, {
4882
+ recipeId,
4883
+ inputs,
4884
+ roomId: options?.roomId,
4885
+ batchAmount: options?.batchAmount,
4886
+ allowPartialBatch: options?.allowPartialBatch,
4887
+ entity: options?.entity
4888
+ });
4889
+ }
4890
+ collectRecipeAsync(runId) {
4891
+ return this.rpcClient.call("H5_SIMULATION_COLLECT_RECIPE" /* H5_SIMULATION_COLLECT_RECIPE */, {
4892
+ runId
4893
+ });
4894
+ }
4895
+ getActiveRunsAsync(options) {
4896
+ return this.rpcClient.call("H5_SIMULATION_GET_ACTIVE_RUNS" /* H5_SIMULATION_GET_ACTIVE_RUNS */, {
4897
+ roomId: options?.roomId
4898
+ });
4899
+ }
4900
+ executeScopedRecipeAsync(recipeId, entity, inputs, options) {
4901
+ return this.rpcClient.call(
4902
+ "H5_SIMULATION_EXECUTE_SCOPED_RECIPE" /* H5_SIMULATION_EXECUTE_SCOPED_RECIPE */,
4783
4903
  {
4784
- roomId: room.id,
4785
- updates,
4786
- merge: options.merge ?? true
4904
+ recipeId,
4905
+ entity,
4906
+ inputs,
4907
+ roomId: options?.roomId ?? null,
4908
+ options
4787
4909
  }
4788
4910
  );
4789
- if (response?.success === false) {
4790
- const errorMessage = typeof response.error === "string" ? response.error : "Failed to update room data";
4791
- throw new Error(errorMessage);
4792
- }
4793
4911
  }
4794
- async getRoomDataAsync(room) {
4795
- const response = await this.rpcClient.call(
4796
- "H5_ROOM_GET_DATA" /* H5_ROOM_GET_DATA */,
4912
+ getAvailableRecipesAsync(options) {
4913
+ return this.rpcClient.call(
4914
+ "H5_SIMULATION_GET_AVAILABLE_RECIPES" /* H5_SIMULATION_GET_AVAILABLE_RECIPES */,
4797
4915
  {
4798
- roomId: room.id
4916
+ roomId: options?.roomId || null,
4917
+ includeActorRecipes: options?.includeActorRecipes || false
4799
4918
  }
4800
4919
  );
4801
- if (response?.success === false) {
4802
- const errorMessage = typeof response.error === "string" ? response.error : "Failed to get room data";
4803
- throw new Error(errorMessage);
4804
- }
4805
- return response.data;
4806
4920
  }
4807
- async sendRoomMessageAsync(venusRoom, request) {
4808
- const response = await this.rpcClient.call(
4809
- "H5_ROOM_SEND_MESSAGE" /* H5_ROOM_SEND_MESSAGE */,
4921
+ getRecipeRequirementsAsync(recipe) {
4922
+ return this.rpcClient.call(
4923
+ "H5_SIMULATION_GET_RECIPE_REQUIREMENTS" /* H5_SIMULATION_GET_RECIPE_REQUIREMENTS */,
4810
4924
  {
4811
- roomId: venusRoom.id,
4812
- message: request.message,
4813
- metadata: request.metadata
4925
+ recipeId: recipe.recipeId,
4926
+ entity: recipe.entity,
4927
+ batchAmount: recipe.batchAmount
4814
4928
  }
4815
4929
  );
4816
- if (response?.success === false) {
4817
- const errorMessage = typeof response.error === "string" ? response.error : "Failed to send message";
4818
- throw new Error(errorMessage);
4819
- }
4820
- return response.messageId;
4821
4930
  }
4822
- async leaveRoomAsync(room) {
4823
- const response = await this.rpcClient.call(
4824
- "H5_ROOM_LEAVE" /* H5_ROOM_LEAVE */,
4931
+ getBatchRecipeRequirementsAsync(recipes) {
4932
+ return this.rpcClient.call(
4933
+ "H5_SIMULATION_GET_BATCH_RECIPE_REQUIREMENTS" /* H5_SIMULATION_GET_BATCH_RECIPE_REQUIREMENTS */,
4825
4934
  {
4826
- roomId: room.id
4935
+ recipes
4827
4936
  }
4828
4937
  );
4829
- if (response?.success === false) {
4830
- const errorMessage = typeof response.error === "string" ? response.error : "Failed to leave room";
4831
- throw new Error(errorMessage);
4832
- }
4833
4938
  }
4834
- async startRoomGameAsync(room, options = {}) {
4835
- const response = await this.rpcClient.call(
4836
- "H5_ROOM_START_GAME" /* H5_ROOM_START_GAME */,
4939
+ triggerRecipeChainAsync(recipeId, options) {
4940
+ return this.rpcClient.call(
4941
+ "H5_SIMULATION_TRIGGER_RECIPE_CHAIN" /* H5_SIMULATION_TRIGGER_RECIPE_CHAIN */,
4837
4942
  {
4838
- roomId: room.id,
4839
- gameConfig: options.gameConfig ?? {},
4840
- turnOrder: options.turnOrder ?? null
4943
+ triggerRecipeId: recipeId,
4944
+ context: options?.context,
4945
+ roomId: options?.roomId
4841
4946
  }
4842
4947
  );
4843
- if (response?.success === false) {
4844
- const errorMessage = typeof response.error === "string" ? response.error : "Failed to start game";
4845
- throw new Error(errorMessage);
4846
- }
4847
4948
  }
4848
- async proposeMoveAsync(room, proposalPayload) {
4949
+ getEntityMetadataAsync(entityId) {
4950
+ return this.rpcClient.call(
4951
+ "H5_SIMULATION_GET_ENTITY_METADATA" /* H5_SIMULATION_GET_ENTITY_METADATA */,
4952
+ {
4953
+ entityId
4954
+ }
4955
+ );
4956
+ }
4957
+ async resolveFieldValueAsync(entityId, fieldPath, entity) {
4849
4958
  const response = await this.rpcClient.call(
4850
- "h5:room:proposeMove" /* H5_ROOM_PROPOSE_MOVE */,
4959
+ "H5_SIMULATION_RESOLVE_VALUE" /* H5_SIMULATION_RESOLVE_VALUE */,
4851
4960
  {
4852
- roomId: room.id,
4853
- gameSpecificState: proposalPayload.gameSpecificState,
4854
- moveType: proposalPayload.moveType,
4855
- clientContext: proposalPayload.clientContext,
4856
- clientProposalId: proposalPayload.clientProposalId
4961
+ entityId,
4962
+ fieldPath,
4963
+ entity
4857
4964
  }
4858
4965
  );
4859
- if (response?.success === false) {
4860
- const errorMessage = typeof response.error === "string" ? response.error : "Failed to propose move";
4861
- throw new Error(errorMessage);
4966
+ return response.value;
4967
+ }
4968
+ };
4969
+
4970
+ // src/simulation/MockSimulationApi.ts
4971
+ function generateAppIdentifier2() {
4972
+ if (typeof window === "undefined") return "unknown-app";
4973
+ const url = window.location.href;
4974
+ const match = url.match(/\/H5\/([^\/]+)/);
4975
+ return match ? match[1] : "unknown-app";
4976
+ }
4977
+ var MockSimulationApi = class {
4978
+ constructor(simulationConfig = null) {
4979
+ __publicField(this, "mockSimulationConfigs", /* @__PURE__ */ new Map());
4980
+ // appIdentifier -> config
4981
+ __publicField(this, "mockSimulationStates", /* @__PURE__ */ new Map());
4982
+ // appIdentifier -> config
4983
+ __publicField(this, "mockActiveTimers", /* @__PURE__ */ new Map());
4984
+ // appIdentifier -> timers[]
4985
+ __publicField(this, "appId");
4986
+ __publicField(this, "providedSimulationConfig");
4987
+ this.appId = generateAppIdentifier2();
4988
+ this.providedSimulationConfig = simulationConfig;
4989
+ }
4990
+ sumContributions(contributions) {
4991
+ return sumContributions(contributions);
4992
+ }
4993
+ async validateSlotAssignmentAsync(containerId, slotId, itemId) {
4994
+ this.log("validateSlotAssignmentAsync called:", {
4995
+ containerId,
4996
+ slotId,
4997
+ itemId
4998
+ });
4999
+ return { valid: true, message: "Mock validation successful" };
5000
+ }
5001
+ async executeBatchOperationsAsync(operations, validateOnly) {
5002
+ this.log("executeBatchOperationsAsync called:", {
5003
+ operations,
5004
+ validateOnly
5005
+ });
5006
+ return {
5007
+ success: true,
5008
+ results: operations.map(() => ({ success: true }))
5009
+ };
5010
+ }
5011
+ async getAvailableItemsAsync(containerId, slotId) {
5012
+ console.log("[Venus Simulation Mock] getAvailableItemsAsync called:", {
5013
+ containerId,
5014
+ slotId
5015
+ });
5016
+ const appIdentifier = generateAppIdentifier2();
5017
+ const mockSimulationConfigs = this.mockSimulationConfigs;
5018
+ const config = mockSimulationConfigs.get(appIdentifier) || {
5019
+ entities: {}
5020
+ };
5021
+ const availableItems = Object.entries(config.entities).slice(0, 3).map(([entityId, entity]) => ({
5022
+ entityId,
5023
+ quantity: 1,
5024
+ metadata: entity.metadata,
5025
+ powerPreview: 100
5026
+ // Mock power value
5027
+ }));
5028
+ return availableItems;
5029
+ }
5030
+ async calculatePowerPreviewAsync(containerId, slotId, candidateItemId) {
5031
+ this.log("calculatePowerPreviewAsync called:", {
5032
+ containerId,
5033
+ slotId,
5034
+ candidateItemId
5035
+ });
5036
+ return {
5037
+ currentPower: 1e3,
5038
+ previewPower: 1200,
5039
+ powerDelta: 200,
5040
+ breakdown: { base: 800, weapon: 200, armor: 200 }
5041
+ };
5042
+ }
5043
+ async getSlotContainersAsync() {
5044
+ this.log("getSlotContainersAsync called");
5045
+ const appIdentifier = this.appId;
5046
+ const mockSimulationConfigs = this.mockSimulationConfigs;
5047
+ const config = mockSimulationConfigs.get(appIdentifier) || {
5048
+ entities: {}
5049
+ };
5050
+ const containers = Object.entries(config.entities).filter(([_2, entity]) => entity.metadata?.slots).map(([entityId, entity]) => ({
5051
+ entityId,
5052
+ slots: entity.metadata?.slots,
5053
+ isOwned: true
5054
+ // Mock: assume all containers are owned
5055
+ }));
5056
+ return containers;
5057
+ }
5058
+ async getSlotAssignmentsAsync(containerId) {
5059
+ this.log("getSlotAssignmentsAsync called for:", containerId);
5060
+ return [];
5061
+ }
5062
+ async resolveFieldValueAsync(entityId, fieldPath, entity) {
5063
+ this.log("resolveFieldValueAsync called:", {
5064
+ entityId,
5065
+ fieldPath,
5066
+ entity
5067
+ });
5068
+ const mockValues = {
5069
+ basePower: 850,
5070
+ weaponPower: 300,
5071
+ armorPower: 150,
5072
+ total_power: 1300,
5073
+ total_defense_power: 5e3
5074
+ };
5075
+ return mockValues[fieldPath] || 100;
5076
+ }
5077
+ async getEntityMetadataAsync(entityId) {
5078
+ this.log("getEntityMetadataAsync called for:", entityId);
5079
+ const mockSimulationConfigs = this.mockSimulationConfigs;
5080
+ const appIdentifier = this.appId;
5081
+ const config = mockSimulationConfigs.get(
5082
+ appIdentifier
5083
+ ) || {
5084
+ entities: {}};
5085
+ const entity = config.entities[entityId];
5086
+ return entity?.metadata || {};
5087
+ }
5088
+ async collectRecipeAsync(runId) {
5089
+ this.log("collectRecipeAsync called:", { runId });
5090
+ const mockRewards = {
5091
+ cash: Math.floor(Math.random() * 1e3) + 500,
5092
+ experience: Math.floor(Math.random() * 50) + 25
5093
+ };
5094
+ return {
5095
+ success: true,
5096
+ runId,
5097
+ rewards: mockRewards,
5098
+ message: "Rewards collected successfully"
5099
+ };
5100
+ }
5101
+ executeRecipeAsync(recipeId, inputs, options) {
5102
+ this.log("executeRecipeAsync called:", {
5103
+ recipeId,
5104
+ inputs,
5105
+ options
5106
+ });
5107
+ const appIdentifier = this.appId;
5108
+ return this.executeRecipe(appIdentifier, recipeId, inputs);
5109
+ }
5110
+ async executeScopedRecipeAsync(recipeId, entity, inputs, options) {
5111
+ this.log("executeScopedRecipeAsync called:", {
5112
+ recipeId,
5113
+ entity,
5114
+ inputs,
5115
+ roomId: options?.roomId,
5116
+ options
5117
+ });
5118
+ return {
5119
+ success: true,
5120
+ message: "Mock scoped recipe execution successful"
5121
+ };
5122
+ }
5123
+ async getActiveRunsAsync(options) {
5124
+ this.log("getActiveRunsAsync called:", options);
5125
+ const appIdentifier = this.appId;
5126
+ let state = this.mockSimulationStates.get(appIdentifier);
5127
+ if (!state) {
5128
+ state = await this.initializeSimulationState(appIdentifier);
4862
5129
  }
4863
- return response.data;
5130
+ return state.activeRuns || [];
5131
+ }
5132
+ async getAvailableRecipesAsync(options) {
5133
+ this.log("getAvailableRecipesAsync called:", options);
5134
+ const baseRecipes = [
5135
+ { id: "collect_resources", scope: "player", clientViewable: true },
5136
+ { id: "upgrade_equipment", scope: "player", clientViewable: true }
5137
+ ];
5138
+ if (options?.roomId) {
5139
+ baseRecipes.push(
5140
+ { id: "room_upgrade", scope: "room", clientViewable: true },
5141
+ { id: "cooperative_project", scope: "room", clientViewable: true }
5142
+ );
5143
+ }
5144
+ if (options?.includeActorRecipes && options?.roomId) {
5145
+ baseRecipes.push(
5146
+ { id: "trade_with_npc", scope: "actor", clientViewable: true },
5147
+ { id: "attack_monster", scope: "actor", clientViewable: true }
5148
+ );
5149
+ }
5150
+ return { success: true, recipes: baseRecipes };
5151
+ }
5152
+ async getBatchRecipeRequirementsAsync(recipes) {
5153
+ this.log("getBatchRecipeRequirementsAsync called:", {
5154
+ count: recipes?.length
5155
+ });
5156
+ const results = (recipes || []).map((q) => ({
5157
+ recipeId: q.recipeId,
5158
+ entity: q.entity || null,
5159
+ amount: q.batchAmount || 1,
5160
+ inputs: { cash: "BE:0" },
5161
+ canAfford: true,
5162
+ disabled: false
5163
+ }));
5164
+ return { success: true, results };
5165
+ }
5166
+ async getRecipeRequirementsAsync(recipe) {
5167
+ this.log("getRecipeRequirementsAsync called:", recipe);
5168
+ return {
5169
+ recipeId: recipe.recipeId,
5170
+ entity: recipe.entity || null,
5171
+ amount: recipe.batchAmount,
5172
+ inputs: { cash: "BE:0" },
5173
+ canAfford: true,
5174
+ disabled: false
5175
+ };
4864
5176
  }
4865
- async validateMoveAsync(_room, moveId, verdict) {
5177
+ async triggerRecipeChainAsync(recipeId, options) {
5178
+ this.log("triggerRecipeChainAsync called:", { recipeId, ...options });
4866
5179
  return {
4867
5180
  success: true,
4868
- moveId,
4869
- isValid: verdict.isValid,
4870
- reason: verdict.reason
5181
+ message: "Mock recipe chain triggered successfully"
4871
5182
  };
4872
5183
  }
4873
- async subscribeAsync(room, options = {}) {
4874
- const roomId = room.id;
4875
- const existingData = this.subscriptions.data[roomId];
4876
- const existingMessages = this.subscriptions.messages[roomId];
4877
- const existingGameEvents = this.subscriptions.gameEvents[roomId];
4878
- const subscribeToData = Boolean(options.onData) && (existingData?.length ?? 0) === 0;
4879
- const subscribeToMessages = Boolean(options.onMessages) && (existingMessages?.length ?? 0) === 0;
4880
- const subscribeToProposedMoves = Boolean(options.onGameEvents) && (existingGameEvents?.length ?? 0) === 0;
4881
- if (subscribeToData || subscribeToMessages || subscribeToProposedMoves) {
4882
- try {
4883
- await this.rpcClient.call("H5_ROOM_SUBSCRIBE" /* H5_ROOM_SUBSCRIBE */, {
4884
- roomId,
4885
- subscribeToData,
4886
- subscribeToMessages,
4887
- subscribeToProposedMoves
4888
- });
4889
- } catch (error) {
4890
- console.error("[Venus SDK] Failed to set up room subscription:", error);
4891
- throw error;
5184
+ log(message, ...args) {
5185
+ console.log(`[Venus Sim Mock] ${message}`, args);
5186
+ }
5187
+ async executeRecipe(appIdentifier, recipeId, inputs) {
5188
+ this.log(`Executing recipe ${recipeId} for ${appIdentifier}`, inputs);
5189
+ const mockSimulationConfigs = this.mockSimulationConfigs;
5190
+ const mockSimulationStates = this.mockSimulationStates;
5191
+ let config = mockSimulationConfigs.get(appIdentifier);
5192
+ let state = mockSimulationStates.get(appIdentifier);
5193
+ if (!config || !state) {
5194
+ state = await this.initializeSimulationState(appIdentifier);
5195
+ config = mockSimulationConfigs.get(appIdentifier);
5196
+ if (!config) {
5197
+ throw new Error("Failed to initialize simulation config");
5198
+ }
5199
+ }
5200
+ const recipe = config.recipes?.[recipeId];
5201
+ if (!recipe) {
5202
+ throw new Error(`Recipe ${recipeId} not found`);
5203
+ }
5204
+ if (state.disabledRecipes?.includes(recipeId)) {
5205
+ throw new Error(`Recipe ${recipeId} is disabled`);
5206
+ }
5207
+ if (recipe.inputs) {
5208
+ for (const [entityId, required] of Object.entries(recipe.inputs)) {
5209
+ const available = state.inventory[entityId] || 0;
5210
+ if (available < required) {
5211
+ throw new Error(
5212
+ `Insufficient ${entityId}: required ${required}, available ${available}`
5213
+ );
5214
+ }
4892
5215
  }
4893
5216
  }
4894
- if (options.onData) {
4895
- if (!this.subscriptions.data[roomId]) {
4896
- this.subscriptions.data[roomId] = [];
5217
+ if (recipe.inputs) {
5218
+ for (const [entityId, input] of Object.entries(recipe.inputs)) {
5219
+ const inventoryValue = state.inventory[entityId] || 0;
5220
+ if (typeof input === "number" && typeof inventoryValue === "number") {
5221
+ state.inventory[entityId] = inventoryValue - input;
5222
+ }
4897
5223
  }
4898
- this.subscriptions.data[roomId].push(options.onData);
4899
5224
  }
4900
- if (options.onMessages) {
4901
- if (!this.subscriptions.messages[roomId]) {
4902
- this.subscriptions.messages[roomId] = [];
4903
- }
4904
- this.subscriptions.messages[roomId].push(options.onMessages);
5225
+ if (recipe.beginEffects) {
5226
+ this.applyEffects(state, recipe.beginEffects);
4905
5227
  }
4906
- if (options.onGameEvents) {
4907
- if (!this.subscriptions.gameEvents[roomId]) {
4908
- this.subscriptions.gameEvents[roomId] = [];
4909
- }
4910
- this.subscriptions.gameEvents[roomId].push(options.onGameEvents);
5228
+ const runId = this.generateRunId();
5229
+ const now = Date.now();
5230
+ const expiresAt = now + (recipe.duration || 0);
5231
+ const run = {
5232
+ id: runId,
5233
+ recipeId,
5234
+ status: "running",
5235
+ startTime: now,
5236
+ expiresAt,
5237
+ inputs: recipe.inputs || {}
5238
+ };
5239
+ state.activeRuns.push(run);
5240
+ if (recipe.duration === 0) {
5241
+ this.completeRun(appIdentifier, runId);
5242
+ return { status: "completed", runId };
5243
+ } else {
5244
+ const mockActiveTimers = this.mockActiveTimers;
5245
+ const timer = setTimeout(() => {
5246
+ this.completeRun(appIdentifier, runId);
5247
+ }, recipe.duration);
5248
+ const timers = mockActiveTimers.get(appIdentifier) || [];
5249
+ timers.push(timer);
5250
+ mockActiveTimers.set(appIdentifier, timers);
5251
+ return {
5252
+ status: "running",
5253
+ runId,
5254
+ expiresAt: new Date(expiresAt).toISOString()
5255
+ };
4911
5256
  }
4912
- let disposed = false;
4913
- return () => {
4914
- if (disposed) return;
4915
- disposed = true;
4916
- if (options.onData) {
4917
- const callbacks = this.subscriptions.data[roomId];
4918
- if (callbacks) {
4919
- const index = callbacks.indexOf(options.onData);
4920
- if (index > -1) {
4921
- callbacks.splice(index, 1);
4922
- }
5257
+ }
5258
+ async initializeSimulationState(appIdentifier) {
5259
+ this.log(`Initializing simulation state for ${appIdentifier}`);
5260
+ const providedSimulationConfig = this.providedSimulationConfig;
5261
+ const mockSimulationConfigs = this.mockSimulationConfigs;
5262
+ const mockSimulationStates = this.mockSimulationStates;
5263
+ const mockActiveTimers = this.mockActiveTimers;
5264
+ const config = providedSimulationConfig || {
5265
+ version: "1.0",
5266
+ entities: {},
5267
+ recipes: {}
5268
+ };
5269
+ mockSimulationConfigs.set(appIdentifier, config);
5270
+ const initialInventory = {};
5271
+ if (providedSimulationConfig && config.entities) {
5272
+ Object.keys(config.entities).forEach((entityId) => {
5273
+ initialInventory[entityId] = 0;
5274
+ });
5275
+ }
5276
+ const state = {
5277
+ inventory: initialInventory,
5278
+ activeRuns: [],
5279
+ disabledRecipes: new Array()
5280
+ };
5281
+ if (config.recipes) {
5282
+ Object.entries(config.recipes).forEach(([recipeId, recipe]) => {
5283
+ if (recipe.metadata?.startsDisabled) {
5284
+ state.disabledRecipes.push(recipeId);
4923
5285
  }
4924
- }
4925
- if (options.onMessages) {
4926
- const callbacks = this.subscriptions.messages[roomId];
4927
- if (callbacks) {
4928
- const index = callbacks.indexOf(options.onMessages);
4929
- if (index > -1) {
4930
- callbacks.splice(index, 1);
5286
+ });
5287
+ }
5288
+ mockSimulationStates.set(appIdentifier, state);
5289
+ mockActiveTimers.set(appIdentifier, []);
5290
+ console.log(
5291
+ `[Venus Simulation Mock] Initialized state for ${appIdentifier}:`,
5292
+ state
5293
+ );
5294
+ if (config.recipes) {
5295
+ Object.entries(config.recipes).forEach(([recipeId, recipe]) => {
5296
+ const isAutoRestart = recipe.autoRestart || recipe.metadata?.autoRestart;
5297
+ if (isAutoRestart && recipe.outputs) {
5298
+ this.log(`Found auto-restart recipe: ${recipeId}`, {
5299
+ topLevelAutoRestart: recipe.autoRestart,
5300
+ metadataAutoRestart: recipe.metadata?.autoRestart,
5301
+ hasOutputs: !!recipe.outputs,
5302
+ duration: recipe.duration
5303
+ });
5304
+ const condition = recipe.maxRestartCondition || recipe.metadata?.maxRestartCondition;
5305
+ if (condition && condition.entity) {
5306
+ const currentAmount = initialInventory[condition.entity] || 0;
5307
+ if (currentAmount < condition.maxValue) {
5308
+ console.log(
5309
+ `[Venus Simulation Mock] Auto-starting ${recipeId} at initialization`,
5310
+ {
5311
+ currentAmount,
5312
+ maxValue: condition.maxValue,
5313
+ entity: condition.entity
5314
+ }
5315
+ );
5316
+ setTimeout(() => {
5317
+ this.executeRecipe(appIdentifier, recipeId, {});
5318
+ }, 1e3);
5319
+ }
5320
+ } else {
5321
+ console.log(
5322
+ `[Venus Simulation Mock] Auto-starting ${recipeId} at initialization (no condition)`
5323
+ );
5324
+ setTimeout(() => {
5325
+ this.executeRecipe(appIdentifier, recipeId, {});
5326
+ }, 1e3);
4931
5327
  }
4932
5328
  }
5329
+ });
5330
+ }
5331
+ return state;
5332
+ }
5333
+ generateRunId() {
5334
+ return "run_" + Date.now() + "_" + Math.random().toString(36).substr(2, 9);
5335
+ }
5336
+ completeRun(appIdentifier, runId) {
5337
+ this.log(`Completing run ${runId} for ${appIdentifier}`);
5338
+ const mockSimulationConfigs = this.mockSimulationConfigs;
5339
+ const mockSimulationStates = this.mockSimulationStates;
5340
+ const config = mockSimulationConfigs.get(appIdentifier);
5341
+ const state = mockSimulationStates.get(appIdentifier);
5342
+ if (!config || !state) return;
5343
+ const runIndex = state.activeRuns.findIndex((r2) => r2.id === runId);
5344
+ if (runIndex === -1) return;
5345
+ const run = state.activeRuns[runIndex];
5346
+ const recipe = config.recipes?.[run.recipeId];
5347
+ if (!recipe) return;
5348
+ const outputs = {};
5349
+ const rng = this.createSeededRandom(runId);
5350
+ if (recipe.outputs) {
5351
+ for (const [entityId, value] of Object.entries(recipe.outputs)) {
5352
+ if (typeof value === "number") {
5353
+ outputs[entityId] = value;
5354
+ } else if (typeof value === "object" && value != null && "min" in value && "max" in value && typeof value.min == "number" && typeof value.max === "number") {
5355
+ outputs[entityId] = Math.floor(rng() * (value.max - value.min + 1)) + value.min;
5356
+ }
4933
5357
  }
4934
- if (options.onGameEvents) {
4935
- const callbacks = this.subscriptions.gameEvents[roomId];
4936
- if (callbacks) {
4937
- const index = callbacks.indexOf(options.onGameEvents);
4938
- if (index > -1) {
4939
- callbacks.splice(index, 1);
4940
- }
5358
+ }
5359
+ for (const [entityId, amount] of Object.entries(outputs)) {
5360
+ state.inventory[entityId] = (state.inventory[entityId] || 0) + amount;
5361
+ }
5362
+ if (recipe.endEffects) {
5363
+ this.applyEffects(state, recipe.endEffects);
5364
+ }
5365
+ run.status = "completed";
5366
+ run.outputs = outputs;
5367
+ state.activeRuns.splice(runIndex, 1);
5368
+ const isAutoRestart = recipe.autoRestart || recipe.metadata?.autoRestart;
5369
+ if (isAutoRestart) {
5370
+ console.log(
5371
+ `[Venus Simulation Mock] Checking auto-restart for ${run.recipeId}`,
5372
+ {
5373
+ topLevelAutoRestart: recipe.autoRestart,
5374
+ metadataAutoRestart: recipe.metadata?.autoRestart,
5375
+ hasCondition: !!(recipe.maxRestartCondition || recipe.metadata?.maxRestartCondition)
5376
+ }
5377
+ );
5378
+ const condition = recipe.maxRestartCondition || recipe.metadata?.maxRestartCondition;
5379
+ if (condition) {
5380
+ const currentAmount = state.inventory[condition.entity] || 0;
5381
+ if (currentAmount < condition.maxValue) {
5382
+ console.log(
5383
+ `[Venus Simulation Mock] Auto-restarting ${run.recipeId}`,
5384
+ {
5385
+ currentAmount,
5386
+ maxValue: condition.maxValue,
5387
+ entity: condition.entity
5388
+ }
5389
+ );
5390
+ setTimeout(() => {
5391
+ this.executeRecipe(appIdentifier, run.recipeId, recipe.inputs || {});
5392
+ }, 1e3);
4941
5393
  }
5394
+ } else {
5395
+ console.log(
5396
+ `[Venus Simulation Mock] Auto-restarting ${run.recipeId} (no condition)`
5397
+ );
5398
+ setTimeout(() => {
5399
+ this.executeRecipe(appIdentifier, run.recipeId, recipe.inputs || {});
5400
+ }, 1e3);
4942
5401
  }
4943
- const hasAnySubscriptions = (this.subscriptions.data[roomId]?.length ?? 0) > 0 || (this.subscriptions.messages[roomId]?.length ?? 0) > 0 || (this.subscriptions.gameEvents[roomId]?.length ?? 0) > 0;
4944
- if (!hasAnySubscriptions) {
4945
- this.rpcClient.call("H5_ROOM_UNSUBSCRIBE" /* H5_ROOM_UNSUBSCRIBE */, {
4946
- roomId
4947
- }).catch((error) => {
4948
- console.error("[Venus SDK] Failed to clean up room subscription:", error);
4949
- });
5402
+ }
5403
+ console.log(
5404
+ `[Venus Simulation Mock] Completed run ${runId}, outputs:`,
5405
+ outputs
5406
+ );
5407
+ }
5408
+ createSeededRandom(seed) {
5409
+ let hash = 0;
5410
+ for (let i = 0; i < seed.length; i++) {
5411
+ const char = seed.charCodeAt(i);
5412
+ hash = (hash << 5) - hash + char;
5413
+ hash = hash & hash;
5414
+ }
5415
+ return () => {
5416
+ hash = (hash * 9301 + 49297) % 233280;
5417
+ return hash / 233280;
5418
+ };
5419
+ }
5420
+ applyEffects(state, effects) {
5421
+ if (!effects || !Array.isArray(effects)) return;
5422
+ for (const effect of effects) {
5423
+ switch (effect.type) {
5424
+ case "set":
5425
+ state.inventory[effect.target] = effect.value;
5426
+ console.log(
5427
+ `[Venus Simulation Mock] Effect: Set ${effect.target} = ${effect.value}`
5428
+ );
5429
+ break;
5430
+ case "add":
5431
+ state.inventory[effect.target] = (state.inventory[effect.target] || 0) + effect.value;
5432
+ console.log(
5433
+ `[Venus Simulation Mock] Effect: Add ${effect.value} to ${effect.target} (new value: ${state.inventory[effect.target]})`
5434
+ );
5435
+ break;
5436
+ case "multiply":
5437
+ state.inventory[effect.target] = (state.inventory[effect.target] || 0) * effect.value;
5438
+ console.log(
5439
+ `[Venus Simulation Mock] Effect: Multiply ${effect.target} by ${effect.value} (new value: ${state.inventory[effect.target]})`
5440
+ );
5441
+ break;
5442
+ case "min":
5443
+ state.inventory[effect.target] = Math.max(
5444
+ state.inventory[effect.target] || 0,
5445
+ effect.value
5446
+ );
5447
+ console.log(
5448
+ `[Venus Simulation Mock] Effect: Set ${effect.target} min ${effect.value} (new value: ${state.inventory[effect.target]})`
5449
+ );
5450
+ break;
5451
+ case "max":
5452
+ state.inventory[effect.target] = Math.min(
5453
+ state.inventory[effect.target] || 0,
5454
+ effect.value
5455
+ );
5456
+ console.log(
5457
+ `[Venus Simulation Mock] Effect: Set ${effect.target} max ${effect.value} (new value: ${state.inventory[effect.target]})`
5458
+ );
5459
+ break;
5460
+ case "enable_recipe":
5461
+ if (state.disabledRecipes?.includes(effect.target)) {
5462
+ state.disabledRecipes = state.disabledRecipes.filter(
5463
+ (r2) => r2 !== effect.target
5464
+ );
5465
+ console.log(
5466
+ `[Venus Simulation Mock] Effect: Enabled recipe ${effect.target}`
5467
+ );
5468
+ }
5469
+ break;
5470
+ case "disable_recipe":
5471
+ if (!state.disabledRecipes) state.disabledRecipes = [];
5472
+ if (!state.disabledRecipes.includes(effect.target)) {
5473
+ state.disabledRecipes.push(effect.target);
5474
+ console.log(
5475
+ `[Venus Simulation Mock] Effect: Disabled recipe ${effect.target}`
5476
+ );
5477
+ }
5478
+ break;
5479
+ case "trigger_recipe":
5480
+ console.log(
5481
+ `[Venus Simulation Mock] Effect: Trigger recipe ${effect.target} (not implemented)`
5482
+ );
5483
+ break;
5484
+ default:
5485
+ console.warn(
5486
+ `[Venus Simulation Mock] Unknown effect type: ${effect.type}`
5487
+ );
4950
5488
  }
5489
+ }
5490
+ }
5491
+ async getConfigAsync() {
5492
+ console.log("[Venus Simulation Mock] getConfigAsync called");
5493
+ const appIdentifier = this.appId;
5494
+ const mockSimulationConfigs = this.mockSimulationConfigs;
5495
+ const config = mockSimulationConfigs.get(appIdentifier) || {
5496
+ version: "1.0",
5497
+ entities: {},
5498
+ recipes: {}
5499
+ };
5500
+ return config;
5501
+ }
5502
+ async getStateAsync(roomId) {
5503
+ this.log("getStateAsync called:", roomId);
5504
+ const appIdentifier = this.appId;
5505
+ const mockSimulationStates = this.mockSimulationStates;
5506
+ let state = mockSimulationStates.get(appIdentifier);
5507
+ if (!state) {
5508
+ state = await this.initializeSimulationState(appIdentifier);
5509
+ }
5510
+ const mockSimulationConfigs = this.mockSimulationConfigs;
5511
+ return {
5512
+ ...state,
5513
+ roomId,
5514
+ configuration: mockSimulationConfigs.get(appIdentifier)
4951
5515
  };
4952
5516
  }
5517
+ async assignItemToSlotAsync(containerId, slotId, itemId) {
5518
+ this.log("assignItemToSlotAsync called:", {
5519
+ containerId,
5520
+ slotId,
5521
+ itemId
5522
+ });
5523
+ return { success: true, message: "Mock assignment successful" };
5524
+ }
5525
+ async removeItemFromSlotAsync(containerId, slotId) {
5526
+ this.log("removeItemFromSlotAsync called:", {
5527
+ containerId,
5528
+ slotId
5529
+ });
5530
+ return { success: true, message: "Mock removal successful" };
5531
+ }
4953
5532
  };
4954
5533
 
4955
- // src/rooms/index.ts
4956
- function bindMethod(target, targetKey, source, sourceKey) {
4957
- const key = sourceKey ?? targetKey;
4958
- const fn = source?.[key];
4959
- if (typeof fn === "function") {
4960
- target[targetKey] = fn.bind(source);
4961
- return true;
4962
- }
4963
- return false;
4964
- }
4965
- function initializeRoomsApi(venusApi, host) {
4966
- const roomsApi = host?.rooms;
4967
- if (!roomsApi) {
4968
- console.warn(
4969
- "[Venus SDK] Host did not provide a rooms implementation. Rooms API will be unavailable."
5534
+ // src/simulation/index.ts
5535
+ function initializeSimulation(venusApi, host) {
5536
+ console.log("[Venus SDK] Initializing new Simulation Api");
5537
+ venusApi.simulation = {
5538
+ isEnabled: () => true
5539
+ };
5540
+ venusApi.simulation.getConfigAsync = () => {
5541
+ return host.simulation.getConfigAsync();
5542
+ };
5543
+ venusApi.simulation.getStateAsync = (options) => {
5544
+ return host.simulation.getStateAsync(options?.roomId);
5545
+ };
5546
+ venusApi.simulation.executeRecipeAsync = (recipeId, inputs, options) => {
5547
+ return host.simulation.executeRecipeAsync(recipeId, inputs, options);
5548
+ };
5549
+ venusApi.simulation.getActiveRunsAsync = () => {
5550
+ return host.simulation.getActiveRunsAsync();
5551
+ };
5552
+ venusApi.simulation.collectRecipeAsync = (runId) => {
5553
+ return host.simulation.collectRecipeAsync(runId);
5554
+ };
5555
+ venusApi.simulation.executeScopedRecipeAsync = (recipeId, entity, inputs, roomId, options) => {
5556
+ return host.simulation.executeScopedRecipeAsync(recipeId, entity, inputs, {
5557
+ roomId,
5558
+ ...options
5559
+ });
5560
+ };
5561
+ venusApi.simulation.triggerRecipeChainAsync = (recipeId, context, roomId) => {
5562
+ return host.simulation.triggerRecipeChainAsync(recipeId, {
5563
+ context,
5564
+ roomId
5565
+ });
5566
+ };
5567
+ venusApi.simulation.getAvailableRecipesAsync = async (roomId, includeActorRecipes) => {
5568
+ const result = await host.simulation.getAvailableRecipesAsync({
5569
+ roomId,
5570
+ includeActorRecipes
5571
+ });
5572
+ return result.recipes;
5573
+ };
5574
+ venusApi.simulation.getRecipeRequirementsAsync = (recipeId, entity, amount) => {
5575
+ return host.simulation.getRecipeRequirementsAsync({
5576
+ recipeId,
5577
+ entity,
5578
+ batchAmount: amount
5579
+ });
5580
+ };
5581
+ venusApi.simulation.getBatchRecipeRequirementsAsync = (recipes) => {
5582
+ return host.simulation.getBatchRecipeRequirementsAsync(recipes);
5583
+ };
5584
+ venusApi.simulation.resolveFieldValueAsync = (entityId, fieldPath, entity) => {
5585
+ return host.simulation.resolveFieldValueAsync(entityId, fieldPath, entity);
5586
+ };
5587
+ venusApi.simulation.getEntityMetadataAsync = (entityId) => {
5588
+ return host.simulation.getEntityMetadataAsync(entityId);
5589
+ };
5590
+ venusApi.simulation.getSlotAssignmentsAsync = (containerId) => {
5591
+ return host.simulation.getSlotAssignmentsAsync(containerId);
5592
+ };
5593
+ venusApi.simulation.getSlotContainersAsync = () => {
5594
+ return host.simulation.getSlotContainersAsync();
5595
+ };
5596
+ venusApi.simulation.assignItemToSlotAsync = (containerId, slotId, itemId) => {
5597
+ return host.simulation.assignItemToSlotAsync(containerId, slotId, itemId);
5598
+ };
5599
+ venusApi.simulation.removeItemFromSlotAsync = (containerId, slotId) => {
5600
+ return host.simulation.removeItemFromSlotAsync(containerId, slotId);
5601
+ };
5602
+ venusApi.simulation.getAvailableItemsAsync = (containerId, slotId) => {
5603
+ return host.simulation.getAvailableItemsAsync(containerId, slotId);
5604
+ };
5605
+ venusApi.simulation.calculatePowerPreviewAsync = (containerId, slotId, candidateItemId) => {
5606
+ return host.simulation.calculatePowerPreviewAsync(
5607
+ containerId,
5608
+ slotId,
5609
+ candidateItemId
4970
5610
  );
4971
- return;
4972
- }
4973
- const venus = venusApi;
4974
- const existingNamespace = venus.rooms || {};
4975
- const roomsNamespace = Object.assign({}, existingNamespace);
4976
- const namespaceBindings = [
4977
- ["createRoomAsync"],
4978
- ["joinOrCreateRoomAsync"],
4979
- ["joinRoomByCodeAsync"],
4980
- ["getUserRoomsAsync"],
4981
- ["subscribeAsync"],
4982
- ["updateRoomDataAsync"],
4983
- ["getRoomDataAsync"],
4984
- ["sendRoomMessageAsync"],
4985
- ["leaveRoomAsync"],
4986
- ["startRoomGameAsync"],
4987
- ["proposeMoveAsync"],
4988
- ["validateMoveAsync"]
4989
- ];
4990
- namespaceBindings.forEach(([targetKey, sourceKey]) => {
4991
- bindMethod(roomsNamespace, targetKey, roomsApi, sourceKey);
4992
- });
4993
- venus.rooms = roomsNamespace;
5611
+ };
5612
+ venusApi.simulation.executeBatchOperationsAsync = (operations, validateOnly) => {
5613
+ return host.simulation.executeBatchOperationsAsync(operations, validateOnly);
5614
+ };
5615
+ venusApi.simulation.validateSlotAssignmentAsync = (containerId, slotId, itemId) => {
5616
+ return host.simulation.validateSlotAssignmentAsync(
5617
+ containerId,
5618
+ slotId,
5619
+ itemId
5620
+ );
5621
+ };
5622
+ venusApi.simulation.sumContributions = (contributions) => {
5623
+ return host.simulation.sumContributions(contributions);
5624
+ };
4994
5625
  }
4995
5626
 
5627
+ // src/MockHost.ts
5628
+ init_rooms();
5629
+
4996
5630
  // src/logging/MockLoggingApi.ts
4997
5631
  var MockLoggingApi = class {
4998
5632
  logDebug(message, ...args) {
@@ -5068,173 +5702,9 @@ function initializeLoggingApi(venusApi, host) {
5068
5702
  };
5069
5703
  }
5070
5704
 
5071
- // src/shared-assets/embeddedLibrariesManifest.ts
5072
- var EMBEDDED_LIBRARIES = [
5073
- {
5074
- libraryKey: "phaser@3.90.0",
5075
- assetKey: "library:phaser@3.90.0",
5076
- packageName: "phaser",
5077
- version: "3.90.0",
5078
- globalVar: "Phaser",
5079
- cdnPath: "phaser/3.90.0/phaser.min.js",
5080
- moduleSpecifiers: [{ match: "exact", value: "phaser" }],
5081
- loadStage: 0,
5082
- enabled: true
5083
- },
5084
- {
5085
- libraryKey: "react@18.3.1",
5086
- assetKey: "library:react@18.3.1",
5087
- packageName: "react",
5088
- version: "18.3.1",
5089
- globalVar: "React",
5090
- cdnPath: "react/18.3.1/react.production.min.js",
5091
- moduleSpecifiers: [
5092
- { match: "exact", value: "react", behavior: "namespace" },
5093
- { match: "exact", value: "react/jsx-runtime", behavior: "react-jsx-runtime" },
5094
- {
5095
- match: "exact",
5096
- value: "react/jsx-dev-runtime",
5097
- behavior: "react-jsx-dev-runtime"
5098
- }
5099
- ],
5100
- loadStage: 0,
5101
- // Must load before ReactDOM
5102
- enabled: true
5103
- },
5104
- {
5105
- libraryKey: "react-dom@18.3.1",
5106
- assetKey: "library:react-dom@18.3.1",
5107
- packageName: "react-dom",
5108
- version: "18.3.1",
5109
- globalVar: "ReactDOM",
5110
- cdnPath: "react-dom/18.3.1/react-dom.production.min.js",
5111
- moduleSpecifiers: [
5112
- { match: "exact", value: "react-dom", behavior: "namespace" },
5113
- { match: "exact", value: "react-dom/client", behavior: "namespace" }
5114
- ],
5115
- loadStage: 1,
5116
- // Depends on React (stage 0)
5117
- enabled: true
5118
- },
5119
- {
5120
- libraryKey: "three@0.170.0",
5121
- assetKey: "library:three@0.170.0",
5122
- packageName: "three",
5123
- version: "0.170.0",
5124
- globalVar: "THREE",
5125
- cdnPath: "three/r170/three.min.js",
5126
- moduleSpecifiers: [
5127
- { match: "exact", value: "three", behavior: "namespace" },
5128
- { match: "prefix", value: "three/examples/jsm/", behavior: "namespace" }
5129
- ],
5130
- loadStage: 0,
5131
- enabled: true
5132
- },
5133
- {
5134
- libraryKey: "matter-js@0.19.0",
5135
- assetKey: "library:matter-js@0.19.0",
5136
- packageName: "matter-js",
5137
- version: "0.19.0",
5138
- globalVar: "Matter",
5139
- cdnPath: "matter-js/0.19.0/matter.min.js",
5140
- moduleSpecifiers: [{ match: "exact", value: "matter-js" }],
5141
- loadStage: 0,
5142
- enabled: true
5143
- },
5144
- {
5145
- libraryKey: "inkjs@2.2.0",
5146
- assetKey: "library:inkjs@2.2.0",
5147
- packageName: "inkjs",
5148
- version: "2.2.0",
5149
- globalVar: "inkjs",
5150
- cdnPath: "inkjs/2.2.0/ink.min.js",
5151
- moduleSpecifiers: [{ match: "exact", value: "inkjs" }],
5152
- loadStage: 0,
5153
- enabled: true
5154
- },
5155
- {
5156
- libraryKey: "zustand@5.0.3",
5157
- assetKey: "library:zustand@5.0.3",
5158
- packageName: "zustand",
5159
- version: "5.0.3",
5160
- globalVar: "zustand",
5161
- cdnPath: "zustand/5.0.3/zustand.min.js",
5162
- moduleSpecifiers: [
5163
- { match: "exact", value: "zustand" },
5164
- { match: "exact", value: "zustand/middleware" }
5165
- ],
5166
- loadStage: 0,
5167
- enabled: true
5168
- },
5169
- {
5170
- libraryKey: "ammo.js@2024.11",
5171
- assetKey: "library:ammo.js@2024.11",
5172
- packageName: "ammo.js",
5173
- version: "2024.11",
5174
- globalVar: "Ammo",
5175
- cdnPath: "ammo/2024.11/ammo.js",
5176
- moduleSpecifiers: [
5177
- { match: "exact", value: "ammo.js" },
5178
- { match: "exact", value: "ammo.js/builds/ammo.wasm.js" }
5179
- ],
5180
- loadStage: 0,
5181
- enabled: false
5182
- // Not ready yet - WASM loading needs additional work
5183
- }
5184
- ];
5185
- var EMBEDDED_LIBRARY_BY_KEY = EMBEDDED_LIBRARIES.reduce(
5186
- (acc, lib) => {
5187
- acc[lib.libraryKey] = lib;
5188
- return acc;
5189
- },
5190
- {}
5191
- );
5192
- EMBEDDED_LIBRARIES.filter(
5193
- (lib) => lib.enabled
5194
- ).flatMap(
5195
- (lib) => lib.moduleSpecifiers.map((specifier) => ({
5196
- ...specifier,
5197
- libraryKey: lib.libraryKey
5198
- }))
5199
- );
5200
- function getLibraryDefinition(libraryKey) {
5201
- const definition = EMBEDDED_LIBRARY_BY_KEY[libraryKey];
5202
- if (!definition) {
5203
- const availableKeys = Object.keys(EMBEDDED_LIBRARY_BY_KEY).join(", ");
5204
- throw new Error(
5205
- `Unsupported embedded library: ${libraryKey}. Available libraries: ${availableKeys}`
5206
- );
5207
- }
5208
- return definition;
5209
- }
5210
-
5211
- // src/shared-assets/base64Utils.ts
5212
- function base64ToArrayBuffer(base64) {
5213
- const binaryString = atob(base64);
5214
- const len = binaryString.length;
5215
- const bytes = new Uint8Array(len);
5216
- for (let i = 0; i < len; i++) {
5217
- bytes[i] = binaryString.charCodeAt(i);
5218
- }
5219
- return bytes.buffer;
5220
- }
5221
- function base64ToUtf8(base64) {
5222
- if (typeof TextDecoder !== "undefined") {
5223
- const decoder = new TextDecoder("utf-8");
5224
- const buffer = base64ToArrayBuffer(base64);
5225
- return decoder.decode(new Uint8Array(buffer));
5226
- }
5227
- if (typeof globalThis !== "undefined" && typeof globalThis.Buffer !== "undefined") {
5228
- const BufferCtor = globalThis.Buffer;
5229
- return BufferCtor.from(base64, "base64").toString("utf-8");
5230
- }
5231
- const binaryString = atob(base64);
5232
- let result = "";
5233
- for (let i = 0; i < binaryString.length; i++) {
5234
- result += String.fromCharCode(binaryString.charCodeAt(i));
5235
- }
5236
- return decodeURIComponent(escape(result));
5237
- }
5705
+ // src/shared-assets/consts.ts
5706
+ var BurgerTimeAssetsCdnPath = "burger-time/Core.stow";
5707
+ var CharacterAssetsCdnPath = "burger-time/Character.stow";
5238
5708
 
5239
5709
  // src/shared-assets/RpcSharedAssetsApi.ts
5240
5710
  var RpcSharedAssetsApi = class {
@@ -5244,48 +5714,46 @@ var RpcSharedAssetsApi = class {
5244
5714
  this.rpcClient = rpcClient;
5245
5715
  this.venusApi = venusApi;
5246
5716
  }
5247
- async loadAssetsBundle(game, bundleKey, fileType = "stow") {
5717
+ async loadBurgerTimeAssetsBundle() {
5248
5718
  try {
5249
5719
  const response = await this.rpcClient.callT("H5_LOAD_EMBEDDED_ASSET" /* H5_LOAD_EMBEDDED_ASSET */, {
5250
- assetKey: bundleKey
5720
+ assetKey: "burgerTimeCoreBundle"
5251
5721
  });
5252
5722
  return base64ToArrayBuffer(response.base64Data);
5253
5723
  } catch (err) {
5254
5724
  try {
5255
- const blob = await this.venusApi.cdn.fetchBlob(`${game}/${bundleKey}.${fileType}`);
5725
+ const blob = await this.venusApi.cdn.fetchBlob(BurgerTimeAssetsCdnPath);
5256
5726
  return await blob.arrayBuffer();
5257
5727
  } catch (e) {
5258
- throw new Error(`Failed to load ${bundleKey}`);
5728
+ throw new Error("Failed to load burgerTimeAssetsBundle");
5259
5729
  }
5260
5730
  }
5261
5731
  }
5262
- async loadLibraryCode(libraryKey) {
5263
- const definition = getLibraryDefinition(libraryKey);
5732
+ async loadCharactersBundle() {
5264
5733
  try {
5265
5734
  const response = await this.rpcClient.callT("H5_LOAD_EMBEDDED_ASSET" /* H5_LOAD_EMBEDDED_ASSET */, {
5266
- assetKey: definition.assetKey
5735
+ assetKey: "characters"
5267
5736
  });
5268
- return base64ToUtf8(response.base64Data);
5737
+ return base64ToArrayBuffer(response.base64Data);
5269
5738
  } catch (err) {
5270
- console.error(
5271
- `[Venus Libraries] Failed to load ${libraryKey} from host via RPC:`,
5272
- err
5273
- );
5274
- console.warn(
5275
- `[Venus Libraries] Falling back to CDN for ${libraryKey}. This may indicate an asset packaging issue.`
5276
- );
5277
5739
  try {
5278
- const cdnUrl = this.venusApi.cdn.resolveSharedLibUrl(definition.cdnPath);
5279
- const response = await this.venusApi.cdn.fetchFromCdn(cdnUrl);
5280
- return await response.text();
5281
- } catch (cdnError) {
5282
- throw new Error(
5283
- `Failed to load embedded library ${libraryKey}: RPC failed, CDN fallback failed: ${cdnError.message}`
5284
- );
5740
+ const blob = await this.venusApi.cdn.fetchBlob(CharacterAssetsCdnPath);
5741
+ return await blob.arrayBuffer();
5742
+ } catch (e) {
5743
+ throw new Error("Failed to load charactersBundle");
5285
5744
  }
5286
5745
  }
5287
5746
  }
5288
5747
  };
5748
+ function base64ToArrayBuffer(base64) {
5749
+ const binaryString = atob(base64);
5750
+ const len = binaryString.length;
5751
+ const bytes = new Uint8Array(len);
5752
+ for (let i = 0; i < len; i++) {
5753
+ bytes[i] = binaryString.charCodeAt(i);
5754
+ }
5755
+ return bytes.buffer;
5756
+ }
5289
5757
 
5290
5758
  // src/shared-assets/MockSharedAssetsApi.ts
5291
5759
  var MockSharedAssetsApi = class {
@@ -5293,15 +5761,13 @@ var MockSharedAssetsApi = class {
5293
5761
  __publicField(this, "venusApi");
5294
5762
  this.venusApi = venusApi;
5295
5763
  }
5296
- async loadAssetsBundle(game, bundleKey, fileType = "stow") {
5297
- const blob = await this.venusApi.cdn.fetchBlob(`${game}/${bundleKey}.${fileType}`);
5764
+ async loadBurgerTimeAssetsBundle() {
5765
+ const blob = await this.venusApi.cdn.fetchBlob(BurgerTimeAssetsCdnPath);
5298
5766
  return await blob.arrayBuffer();
5299
5767
  }
5300
- async loadLibraryCode(libraryKey) {
5301
- const definition = getLibraryDefinition(libraryKey);
5302
- const url = this.venusApi.cdn.resolveSharedLibUrl(definition.cdnPath);
5303
- const response = await this.venusApi.cdn.fetchFromCdn(url);
5304
- return await response.text();
5768
+ async loadCharactersBundle() {
5769
+ const blob = await this.venusApi.cdn.fetchBlob(CharacterAssetsCdnPath);
5770
+ return await blob.arrayBuffer();
5305
5771
  }
5306
5772
  };
5307
5773
 
@@ -5382,116 +5848,44 @@ var ROOMS_UNAVAILABLE_MESSAGE = "[Venus SDK] Rooms API is only available when ru
5382
5848
  function createUnavailableRoomsApi() {
5383
5849
  const roomsUnavailableError = () => new Error(ROOMS_UNAVAILABLE_MESSAGE);
5384
5850
  return {
5385
- async createRoomAsync() {
5851
+ async createRoom() {
5386
5852
  throw roomsUnavailableError();
5387
5853
  },
5388
- async joinOrCreateRoomAsync() {
5854
+ async joinOrCreateRoom() {
5389
5855
  throw roomsUnavailableError();
5390
5856
  },
5391
- async joinRoomByCodeAsync() {
5857
+ async getUserRooms() {
5392
5858
  throw roomsUnavailableError();
5393
5859
  },
5394
- async getUserRoomsAsync() {
5860
+ async joinRoomByCode() {
5395
5861
  throw roomsUnavailableError();
5396
5862
  },
5397
- async subscribeAsync() {
5863
+ subscribe() {
5398
5864
  throw roomsUnavailableError();
5399
5865
  },
5400
- async updateRoomDataAsync() {
5866
+ async updateData() {
5401
5867
  throw roomsUnavailableError();
5402
5868
  },
5403
- async getRoomDataAsync() {
5869
+ async getData() {
5404
5870
  throw roomsUnavailableError();
5405
5871
  },
5406
- async sendRoomMessageAsync() {
5872
+ async sendMessage() {
5407
5873
  throw roomsUnavailableError();
5408
5874
  },
5409
- async leaveRoomAsync() {
5875
+ async leave() {
5410
5876
  throw roomsUnavailableError();
5411
5877
  },
5412
- async startRoomGameAsync() {
5878
+ async startGame() {
5413
5879
  throw roomsUnavailableError();
5414
5880
  },
5415
- async proposeMoveAsync() {
5881
+ async proposeMove() {
5416
5882
  throw roomsUnavailableError();
5417
5883
  },
5418
- async validateMoveAsync() {
5884
+ async validateMove() {
5419
5885
  throw roomsUnavailableError();
5420
5886
  }
5421
5887
  };
5422
5888
  }
5423
- var SIMULATION_UNAVAILABLE_MESSAGE = "[Venus SDK] Simulation API is only available when running inside the Venus host environment.";
5424
- function createUnavailableSimulationApi() {
5425
- const simulationUnavailableError = () => new Error(SIMULATION_UNAVAILABLE_MESSAGE);
5426
- return {
5427
- isEnabled() {
5428
- return false;
5429
- },
5430
- async getStateAsync() {
5431
- throw simulationUnavailableError();
5432
- },
5433
- async getConfigAsync() {
5434
- throw simulationUnavailableError();
5435
- },
5436
- async executeRecipeAsync() {
5437
- throw simulationUnavailableError();
5438
- },
5439
- async getActiveRunsAsync() {
5440
- throw simulationUnavailableError();
5441
- },
5442
- async collectRecipeAsync() {
5443
- throw simulationUnavailableError();
5444
- },
5445
- async executeScopedRecipeAsync() {
5446
- throw simulationUnavailableError();
5447
- },
5448
- async triggerRecipeChainAsync() {
5449
- throw simulationUnavailableError();
5450
- },
5451
- async getAvailableRecipesAsync() {
5452
- throw simulationUnavailableError();
5453
- },
5454
- async getRecipeRequirementsAsync() {
5455
- throw simulationUnavailableError();
5456
- },
5457
- async getBatchRecipeRequirementsAsync() {
5458
- throw simulationUnavailableError();
5459
- },
5460
- async resolveFieldValueAsync() {
5461
- throw simulationUnavailableError();
5462
- },
5463
- async getEntityMetadataAsync() {
5464
- throw simulationUnavailableError();
5465
- },
5466
- async getSlotContainersAsync() {
5467
- throw simulationUnavailableError();
5468
- },
5469
- async getSlotAssignmentsAsync() {
5470
- throw simulationUnavailableError();
5471
- },
5472
- async assignItemToSlotAsync() {
5473
- throw simulationUnavailableError();
5474
- },
5475
- async removeItemFromSlotAsync() {
5476
- throw simulationUnavailableError();
5477
- },
5478
- async getAvailableItemsAsync() {
5479
- throw simulationUnavailableError();
5480
- },
5481
- async calculatePowerPreviewAsync() {
5482
- throw simulationUnavailableError();
5483
- },
5484
- async validateSlotAssignmentAsync() {
5485
- throw simulationUnavailableError();
5486
- },
5487
- async executeBatchOperationsAsync() {
5488
- throw simulationUnavailableError();
5489
- },
5490
- async subscribeAsync() {
5491
- throw simulationUnavailableError();
5492
- }
5493
- };
5494
- }
5495
5889
  var MockHost = class {
5496
5890
  constructor(venusApi) {
5497
5891
  __publicField(this, "ads");
@@ -5504,9 +5898,9 @@ var MockHost = class {
5504
5898
  __publicField(this, "notifications");
5505
5899
  __publicField(this, "popups");
5506
5900
  __publicField(this, "profile");
5507
- __publicField(this, "system");
5508
5901
  __publicField(this, "cdn");
5509
5902
  __publicField(this, "time");
5903
+ __publicField(this, "post");
5510
5904
  __publicField(this, "ai");
5511
5905
  __publicField(this, "haptics");
5512
5906
  __publicField(this, "features");
@@ -5538,17 +5932,15 @@ var MockHost = class {
5538
5932
  this.navigation = new MockNavigationApi(venusApi);
5539
5933
  this.notifications = new MockNotificationsApi(venusApi);
5540
5934
  this.popups = new MockPopupsApi(this._overlay);
5541
- this.profile = new MockProfileApi(venusApi);
5542
- const deviceApi = new MockDeviceApi(venusApi);
5543
- const environmentApi = new MockEnvironmentApi(venusApi);
5544
- this.system = new MockSystemApi(deviceApi, environmentApi, venusApi);
5545
- this.cdn = new MockCdnApi(venusApi);
5935
+ this.profile = new MockProfileApi();
5936
+ this.cdn = new MockCdnApi();
5546
5937
  this.time = new MockTimeApi(venusApi);
5938
+ this.post = new MockPostApi(venusApi);
5547
5939
  this.ai = new MockAiApi();
5548
5940
  this.haptics = new MockHapticsApi(venusApi);
5549
5941
  this.features = new MockFeaturesApi();
5550
5942
  this.lifecycle = this._mockLifecyclesApi;
5551
- this.simulation = createUnavailableSimulationApi();
5943
+ this.simulation = new MockSimulationApi();
5552
5944
  this.rooms = createUnavailableRoomsApi();
5553
5945
  this.logging = new MockLoggingApi();
5554
5946
  this.iap = new MockIapApi();
@@ -5564,17 +5956,40 @@ var MockHost = class {
5564
5956
  }
5565
5957
  initialize(options) {
5566
5958
  this._isInitialized = true;
5567
- this.venusApi._profileData = this.profile.getCurrentProfile();
5568
- this.venusApi._deviceData = this.system.getDevice();
5569
- this.venusApi._environmentData = this.system.getEnvironment();
5570
- this.venusApi._localeData = this.venusApi._mock?.locale || "en-US";
5571
- this.venusApi._languageCodeData = this.venusApi._mock?.languageCode || "en";
5959
+ const controls = this.updateUiControls();
5572
5960
  return Promise.resolve({
5573
5961
  initializeAsleep: false,
5574
- safeArea: this.venusApi._safeAreaData
5962
+ hudInsets: {
5963
+ top: controls.feedHeader.height,
5964
+ bottom: 0,
5965
+ left: 0,
5966
+ right: 0
5967
+ }
5575
5968
  });
5576
5969
  }
5970
+ updateUiControls() {
5971
+ const controls = {
5972
+ closeButton: { x: 16, y: 16, width: 32, height: 32 },
5973
+ menuButton: {
5974
+ x: window.innerWidth - 48,
5975
+ y: 16,
5976
+ width: 32,
5977
+ height: 32
5978
+ },
5979
+ feedHeader: { x: 0, y: 0, width: window.innerWidth, height: 56 },
5980
+ playButton: {
5981
+ x: 0,
5982
+ y: window.innerHeight - 60,
5983
+ width: window.innerWidth,
5984
+ height: 60
5985
+ }
5986
+ };
5987
+ return controls;
5988
+ }
5577
5989
  createOverlay() {
5990
+ const venusApi = this.venusApi;
5991
+ venusApi.config.ui.controls = this.updateUiControls();
5992
+ const uiControls = venusApi.config.ui.controls;
5578
5993
  const overlayContainer = document.createElement("div");
5579
5994
  overlayContainer.id = "venus-mock-overlay";
5580
5995
  overlayContainer.style.cssText = `
@@ -5590,7 +6005,7 @@ var MockHost = class {
5590
6005
  const menuButton = this.createOverlayButton(
5591
6006
  "close",
5592
6007
  "Menu",
5593
- { x: window.innerWidth - 48, y: 16, width: 32, height: 32 },
6008
+ uiControls.menuButton,
5594
6009
  () => {
5595
6010
  this.handleMenuButtonClicked();
5596
6011
  },
@@ -5819,13 +6234,17 @@ var MockHost = class {
5819
6234
  return button;
5820
6235
  }
5821
6236
  updateOverlayLayout() {
6237
+ const venusApi = this.venusApi;
5822
6238
  const overlay = this._overlay;
6239
+ venusApi.config.ui.controls = this.updateUiControls();
6240
+ const uiControls = venusApi.config.ui.controls;
5823
6241
  const menuBtn = overlay.elements.menuButton;
5824
- menuBtn.style.left = `${window.innerWidth - 48}px`;
5825
- menuBtn.style.top = "16px";
5826
- menuBtn.style.width = "32px";
5827
- menuBtn.style.minWidth = "32px";
5828
- menuBtn.style.height = "32px";
6242
+ const menuPos = uiControls.menuButton;
6243
+ menuBtn.style.left = `${menuPos.x}px`;
6244
+ menuBtn.style.top = `${menuPos.y}px`;
6245
+ menuBtn.style.width = `${menuPos.width}px`;
6246
+ menuBtn.style.minWidth = `${menuPos.width}px`;
6247
+ menuBtn.style.height = `${menuPos.height}px`;
5829
6248
  }
5830
6249
  triggerLifecycleEvent(name) {
5831
6250
  console.log("Trigger Lifecycle Event: ", name);
@@ -6013,11 +6432,6 @@ var MockHost = class {
6013
6432
  }
6014
6433
  };
6015
6434
 
6016
- // src/utils/idGenerator.ts
6017
- function generateId() {
6018
- return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
6019
- }
6020
-
6021
6435
  // src/rpc/RpcClient.ts
6022
6436
  var RpcClient = class {
6023
6437
  constructor() {
@@ -6060,7 +6474,7 @@ var RpcClient = class {
6060
6474
  }
6061
6475
  async call(method, args, timeout = 5e3) {
6062
6476
  return new Promise((resolve, reject) => {
6063
- const id = generateId();
6477
+ const id = this.generateId();
6064
6478
  this.addPendingCall(id, resolve, reject);
6065
6479
  const request = {
6066
6480
  type: "rpc-request",
@@ -6097,6 +6511,9 @@ var RpcClient = class {
6097
6511
  getPendingCall(id) {
6098
6512
  return this.pendingCalls.get(id);
6099
6513
  }
6514
+ generateId() {
6515
+ return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
6516
+ }
6100
6517
  handleRpcResponse(response) {
6101
6518
  const pending = this.getPendingCall(response.id);
6102
6519
  if (!pending) {
@@ -6159,16 +6576,6 @@ var VenusTransport = class {
6159
6576
  this.isProcessingMessage = false;
6160
6577
  return;
6161
6578
  }
6162
- if (message.type === "H5_SIMULATION_UPDATE" /* H5_SIMULATION_UPDATE */) {
6163
- const notification = {
6164
- type: "rpc-notification",
6165
- id: message.type,
6166
- payload: message.data
6167
- };
6168
- this.handleNotification(notification);
6169
- this.isProcessingMessage = false;
6170
- return;
6171
- }
6172
6579
  const requestId = messageData.requestId;
6173
6580
  if (!requestId) {
6174
6581
  this.logWarn("No requestId. Ignoring message...");
@@ -6335,361 +6742,294 @@ var VenusTransport = class {
6335
6742
  }
6336
6743
  };
6337
6744
 
6338
- // src/simulation/RpcSimulationApi.ts
6339
- var RpcSimulationApi = class {
6745
+ // src/RemoteHost.ts
6746
+ init_rooms();
6747
+
6748
+ // src/rooms/RpcRoomsApi.ts
6749
+ init_VenusRoom();
6750
+ var RpcRoomsApi = class {
6340
6751
  constructor(rpcClient) {
6341
6752
  __publicField(this, "rpcClient");
6342
- __publicField(this, "_simulationConfig", null);
6343
- __publicField(this, "subscriptionCallbacks", /* @__PURE__ */ new Map());
6753
+ __publicField(this, "subscriptions");
6754
+ __publicField(this, "transportSubscription", null);
6344
6755
  this.rpcClient = rpcClient;
6345
- this.rpcClient.onNotification(
6346
- "H5_SIMULATION_UPDATE" /* H5_SIMULATION_UPDATE */,
6347
- this.handleSimulationUpdate.bind(this)
6348
- );
6756
+ this.subscriptions = {
6757
+ data: {},
6758
+ messages: {},
6759
+ gameEvents: {},
6760
+ allEvents: {}
6761
+ };
6349
6762
  }
6350
- isEnabled() {
6351
- return true;
6763
+ /**
6764
+ * Get the subscription state for external access (used by setupRoomNotifications)
6765
+ */
6766
+ getSubscriptions() {
6767
+ return this.subscriptions;
6352
6768
  }
6353
- async validateSlotAssignmentAsync(containerId, slotId, itemId) {
6354
- return this.rpcClient.call(
6355
- "H5_SIMULATION_VALIDATE_ASSIGNMENT" /* H5_SIMULATION_VALIDATE_ASSIGNMENT */,
6356
- {
6357
- containerId,
6358
- slotId,
6359
- itemId
6360
- }
6769
+ /**
6770
+ * Set up room notification routing from the transport
6771
+ */
6772
+ setupNotifications(transport) {
6773
+ const { setupRoomNotifications: setupRoomNotifications2 } = (init_rooms(), __toCommonJS(rooms_exports));
6774
+ this.transportSubscription = setupRoomNotifications2(
6775
+ transport,
6776
+ () => this.getSubscriptions()
6361
6777
  );
6362
6778
  }
6363
- async subscribeAsync(options) {
6364
- this.ensureValidSubscribeOptions(options);
6365
- const subscriptionId = generateId();
6366
- this.subscriptionCallbacks.set(subscriptionId, options.onUpdate);
6367
- try {
6368
- await this.rpcClient.call("H5_SIMULATION_SUBSCRIBE" /* H5_SIMULATION_SUBSCRIBE */, {
6369
- subscriptionId,
6370
- entities: options.entities,
6371
- tags: options.tags,
6372
- activeRuns: options.activeRuns,
6373
- roomId: options.roomId
6374
- });
6375
- } catch (error) {
6376
- this.subscriptionCallbacks.delete(subscriptionId);
6377
- throw error;
6779
+ /**
6780
+ * Clean up subscriptions and resources
6781
+ */
6782
+ dispose() {
6783
+ if (this.transportSubscription) {
6784
+ this.transportSubscription.unsubscribe();
6785
+ this.transportSubscription = null;
6786
+ console.log("[Venus Rooms] Cleaned up room notification subscription");
6378
6787
  }
6379
- let unsubscribed = false;
6380
- return () => {
6381
- if (unsubscribed) {
6382
- return;
6383
- }
6384
- unsubscribed = true;
6385
- this.subscriptionCallbacks.delete(subscriptionId);
6386
- void this.rpcClient.call("H5_SIMULATION_UNSUBSCRIBE" /* H5_SIMULATION_UNSUBSCRIBE */, {
6387
- subscriptionId
6388
- }).catch((error) => {
6389
- console.error(
6390
- "[Venus SDK] Failed to unsubscribe simulation listener",
6391
- error
6392
- );
6393
- });
6394
- };
6395
- }
6396
- executeBatchOperationsAsync(operations, validateOnly) {
6397
- return this.rpcClient.call(
6398
- "H5_SIMULATION_BATCH_OPERATIONS" /* H5_SIMULATION_BATCH_OPERATIONS */,
6399
- {
6400
- operations,
6401
- validateOnly
6402
- }
6403
- );
6404
6788
  }
6405
- async getAvailableItemsAsync(containerId, slotId) {
6789
+ async createRoom(options) {
6406
6790
  const response = await this.rpcClient.call(
6407
- "H5_SIMULATION_GET_AVAILABLE_ITEMS" /* H5_SIMULATION_GET_AVAILABLE_ITEMS */,
6408
- {
6409
- containerId,
6410
- slotId
6411
- }
6412
- );
6413
- return response.availableItems || [];
6414
- }
6415
- calculatePowerPreviewAsync(containerId, slotId, candidateItemId) {
6416
- return this.rpcClient.call(
6417
- "H5_SIMULATION_CALCULATE_POWER_PREVIEW" /* H5_SIMULATION_CALCULATE_POWER_PREVIEW */,
6418
- {
6419
- containerId,
6420
- slotId,
6421
- candidateItemId
6422
- }
6423
- );
6424
- }
6425
- assignItemToSlotAsync(containerId, slotId, itemId) {
6426
- return this.rpcClient.call(
6427
- "H5_SIMULATION_ASSIGN_ITEM" /* H5_SIMULATION_ASSIGN_ITEM */,
6428
- {
6429
- containerId,
6430
- slotId,
6431
- itemId
6432
- }
6433
- );
6434
- }
6435
- removeItemFromSlotAsync(containerId, slotId) {
6436
- return this.rpcClient.call(
6437
- "H5_SIMULATION_REMOVE_ITEM" /* H5_SIMULATION_REMOVE_ITEM */,
6791
+ "H5_ROOM_CREATE" /* H5_ROOM_CREATE */,
6438
6792
  {
6439
- containerId,
6440
- slotId
6793
+ options
6441
6794
  }
6442
6795
  );
6796
+ if (response.success === false) {
6797
+ throw new Error(response.error || "Failed to create room");
6798
+ }
6799
+ const roomData = response.roomData || response;
6800
+ const room = new VenusRoom(roomData);
6801
+ return room;
6443
6802
  }
6444
- async getSlotContainersAsync() {
6445
- const response = await this.rpcClient.call(
6446
- "H5_SIMULATION_GET_CONTAINERS" /* H5_SIMULATION_GET_CONTAINERS */,
6447
- {}
6448
- );
6449
- return response.containers || [];
6450
- }
6451
- async getSlotAssignmentsAsync(containerId) {
6803
+ async joinOrCreateRoom(options) {
6452
6804
  const response = await this.rpcClient.call(
6453
- "H5_SIMULATION_GET_ASSIGNMENTS" /* H5_SIMULATION_GET_ASSIGNMENTS */,
6805
+ "H5_ROOM_JOIN_OR_CREATE" /* H5_ROOM_JOIN_OR_CREATE */,
6454
6806
  {
6455
- containerId
6807
+ options
6456
6808
  }
6457
6809
  );
6458
- return Array.isArray(response) ? response : response.assignments || [];
6810
+ if (response.success === false) {
6811
+ throw new Error(response.error || "Failed to join or create room");
6812
+ }
6813
+ const data = response.value || response;
6814
+ const room = new VenusRoom(data.roomData);
6815
+ return {
6816
+ action: data.action,
6817
+ room,
6818
+ playersJoined: data.playersJoined
6819
+ };
6459
6820
  }
6460
- async getStateAsync(roomId) {
6821
+ async joinRoomByCode(roomCode) {
6461
6822
  const response = await this.rpcClient.call(
6462
- "H5_SIMULATION_GET_STATE" /* H5_SIMULATION_GET_STATE */,
6823
+ "H5_ROOM_JOIN_BY_CODE" /* H5_ROOM_JOIN_BY_CODE */,
6463
6824
  {
6464
- roomId
6825
+ roomCode
6465
6826
  }
6466
6827
  );
6467
- if (response.configuration) {
6468
- this._simulationConfig = response.configuration;
6828
+ if (response?.success === false) {
6829
+ throw new Error(response.error || "Failed to join room by code");
6469
6830
  }
6470
- return response;
6831
+ const roomData = response.roomData || response;
6832
+ const room = new VenusRoom(roomData);
6833
+ return room;
6471
6834
  }
6472
- async getConfigAsync(roomId) {
6473
- if (this._simulationConfig) {
6474
- return this._simulationConfig;
6475
- }
6476
- const config = await this.rpcClient.call(
6477
- "H5_SIMULATION_GET_CONFIG" /* H5_SIMULATION_GET_CONFIG */,
6835
+ // Get user's rooms with optional filtering
6836
+ async getUserRooms(includeArchived = false) {
6837
+ const response = await this.rpcClient.call(
6838
+ "H5_ROOM_GET_USER_ROOMS" /* H5_ROOM_GET_USER_ROOMS */,
6478
6839
  {
6479
- roomId
6840
+ includeArchived
6480
6841
  }
6481
6842
  );
6482
- if (config) {
6483
- this._simulationConfig = config;
6484
- return config;
6843
+ if (response?.success === false) {
6844
+ throw new Error(response.error || "Failed to get user rooms");
6485
6845
  }
6486
- throw new Error("No simulation configuration available");
6487
- }
6488
- executeRecipeAsync(recipeId, inputs, options) {
6489
- return this.rpcClient.call(
6490
- "H5_SIMULATION_EXECUTE_RECIPE" /* H5_SIMULATION_EXECUTE_RECIPE */,
6491
- {
6492
- recipeId,
6493
- inputs,
6494
- roomId: options?.roomId,
6495
- batchAmount: options?.batchAmount,
6496
- allowPartialBatch: options?.allowPartialBatch,
6497
- entity: options?.entity
6498
- }
6499
- );
6500
- }
6501
- collectRecipeAsync(runId) {
6502
- return this.rpcClient.call("H5_SIMULATION_COLLECT_RECIPE" /* H5_SIMULATION_COLLECT_RECIPE */, {
6503
- runId
6504
- });
6505
- }
6506
- getActiveRunsAsync(options) {
6507
- return this.rpcClient.call(
6508
- "H5_SIMULATION_GET_ACTIVE_RUNS" /* H5_SIMULATION_GET_ACTIVE_RUNS */,
6509
- {
6510
- roomId: options?.roomId
6511
- }
6512
- );
6513
- }
6514
- executeScopedRecipeAsync(recipeId, entity, inputs, options) {
6515
- return this.rpcClient.call(
6516
- "H5_SIMULATION_EXECUTE_SCOPED_RECIPE" /* H5_SIMULATION_EXECUTE_SCOPED_RECIPE */,
6517
- {
6518
- recipeId,
6519
- entity,
6520
- inputs,
6521
- roomId: options?.roomId ?? null,
6522
- options
6846
+ const rawRooms = response.rooms || [];
6847
+ const venusRooms = [];
6848
+ for (const roomData of rawRooms) {
6849
+ if (!roomData.id) {
6850
+ console.warn("getUserRooms: Skipping room with missing ID:", roomData);
6851
+ continue;
6523
6852
  }
6524
- );
6853
+ try {
6854
+ const venusRoom = new VenusRoom(roomData);
6855
+ venusRooms.push(venusRoom);
6856
+ } catch (error) {
6857
+ console.warn(
6858
+ "getUserRooms: Failed to create VenusRoom object:",
6859
+ error,
6860
+ roomData
6861
+ );
6862
+ }
6863
+ }
6864
+ return venusRooms;
6525
6865
  }
6526
- getAvailableRecipesAsync(options) {
6527
- return this.rpcClient.call(
6528
- "H5_SIMULATION_GET_AVAILABLE_RECIPES" /* H5_SIMULATION_GET_AVAILABLE_RECIPES */,
6866
+ async updateData(room, updates, merge = true) {
6867
+ const response = await this.rpcClient.call(
6868
+ "H5_ROOM_UPDATE_DATA" /* H5_ROOM_UPDATE_DATA */,
6529
6869
  {
6530
- roomId: options?.roomId || null,
6531
- includeActorRecipes: options?.includeActorRecipes || false
6870
+ roomId: room.id,
6871
+ updates,
6872
+ merge
6532
6873
  }
6533
6874
  );
6875
+ if (response?.success === false) {
6876
+ throw new Error(response.error || "Failed to update room data");
6877
+ }
6878
+ return response.data;
6534
6879
  }
6535
- getRecipeRequirementsAsync(recipe) {
6536
- return this.rpcClient.call(
6537
- "H5_SIMULATION_GET_RECIPE_REQUIREMENTS" /* H5_SIMULATION_GET_RECIPE_REQUIREMENTS */,
6880
+ async getData(room) {
6881
+ const response = await this.rpcClient.call(
6882
+ "H5_ROOM_GET_DATA" /* H5_ROOM_GET_DATA */,
6538
6883
  {
6539
- recipeId: recipe.recipeId,
6540
- entity: recipe.entity,
6541
- batchAmount: recipe.batchAmount
6884
+ roomId: room.id
6542
6885
  }
6543
6886
  );
6887
+ if (response?.success === false) {
6888
+ throw new Error(response.error || "Failed to get room data");
6889
+ }
6890
+ return response.data;
6544
6891
  }
6545
- getBatchRecipeRequirementsAsync(recipes) {
6546
- return this.rpcClient.call(
6547
- "H5_SIMULATION_GET_BATCH_RECIPE_REQUIREMENTS" /* H5_SIMULATION_GET_BATCH_RECIPE_REQUIREMENTS */,
6892
+ async sendMessage(venusRoom, messageData) {
6893
+ const response = await this.rpcClient.call(
6894
+ "H5_ROOM_SEND_MESSAGE" /* H5_ROOM_SEND_MESSAGE */,
6548
6895
  {
6549
- recipes
6896
+ roomId: venusRoom.id,
6897
+ message: messageData
6550
6898
  }
6551
6899
  );
6900
+ if (response?.success === false) {
6901
+ throw new Error(response.error || "Failed to send message");
6902
+ }
6903
+ return response.messageId;
6552
6904
  }
6553
- triggerRecipeChainAsync(recipeId, options) {
6554
- return this.rpcClient.call(
6555
- "H5_SIMULATION_TRIGGER_RECIPE_CHAIN" /* H5_SIMULATION_TRIGGER_RECIPE_CHAIN */,
6905
+ async leave(room) {
6906
+ const response = await this.rpcClient.call(
6907
+ "H5_ROOM_LEAVE" /* H5_ROOM_LEAVE */,
6556
6908
  {
6557
- triggerRecipeId: recipeId,
6558
- context: options?.context,
6559
- roomId: options?.roomId
6909
+ roomId: room.id
6560
6910
  }
6561
6911
  );
6912
+ if (response?.success === false) {
6913
+ throw new Error(response.error || "Failed to leave room");
6914
+ }
6915
+ return response;
6562
6916
  }
6563
- getEntityMetadataAsync(entityId) {
6564
- return this.rpcClient.call(
6565
- "H5_SIMULATION_GET_ENTITY_METADATA" /* H5_SIMULATION_GET_ENTITY_METADATA */,
6917
+ async startGame(room, gameConfig = {}, turnOrder = null) {
6918
+ const response = await this.rpcClient.call(
6919
+ "H5_ROOM_START_GAME" /* H5_ROOM_START_GAME */,
6566
6920
  {
6567
- entityId
6921
+ roomId: room.id,
6922
+ gameConfig,
6923
+ turnOrder
6568
6924
  }
6569
6925
  );
6926
+ if (response?.success === false) {
6927
+ throw new Error(response.error || "Failed to start game");
6928
+ }
6929
+ return response.data;
6570
6930
  }
6571
- async resolveFieldValueAsync(entityId, fieldPath, entity) {
6931
+ async proposeMove(room, proposalPayload) {
6572
6932
  const response = await this.rpcClient.call(
6573
- "H5_SIMULATION_RESOLVE_VALUE" /* H5_SIMULATION_RESOLVE_VALUE */,
6933
+ "h5:room:proposeMove" /* H5_ROOM_PROPOSE_MOVE */,
6574
6934
  {
6575
- entityId,
6576
- fieldPath,
6577
- entity
6935
+ roomId: room.id,
6936
+ gameSpecificState: proposalPayload.gameSpecificState,
6937
+ moveType: proposalPayload.moveType,
6938
+ clientContext: proposalPayload.clientContext,
6939
+ clientProposalId: proposalPayload.clientProposalId
6578
6940
  }
6579
6941
  );
6580
- return response.value;
6581
- }
6582
- handleSimulationUpdate(notification) {
6583
- if (!notification || !notification.subscriptionId) {
6584
- console.warn("[Venus SDK] Received malformed simulation update");
6585
- return;
6586
- }
6587
- const callback = this.subscriptionCallbacks.get(notification.subscriptionId);
6588
- if (!callback) {
6589
- console.warn(
6590
- "[Venus SDK] Received update for unknown subscription:",
6591
- notification.subscriptionId
6592
- );
6593
- return;
6942
+ if (response?.success === false) {
6943
+ throw new Error(response.error || "Failed to propose move");
6594
6944
  }
6595
- try {
6596
- callback(notification.updates);
6597
- } catch (error) {
6598
- console.error("[Venus SDK] Error in simulation subscription callback", error);
6945
+ return response.data;
6946
+ }
6947
+ async validateMove(room, moveId, isValid, reason = null, validatorId = null) {
6948
+ console.log(`[Venus Rooms] Validating move ${moveId}: ${isValid}`);
6949
+ return { success: true, moveId, isValid, reason };
6950
+ }
6951
+ async roomSubscribeToGameEvents(room, callback) {
6952
+ "game_" + Date.now() + "_" + Math.random().toString(36).substr(2, 9);
6953
+ if (!this.subscriptions.gameEvents[room.id]) {
6954
+ this.subscriptions.gameEvents[room.id] = [];
6599
6955
  }
6956
+ this.subscriptions.gameEvents[room.id].push(callback);
6600
6957
  }
6601
- ensureValidSubscribeOptions(options) {
6602
- if (typeof options !== "object" || options === null) {
6603
- throw new Error("Simulation subscribe requires an options object");
6958
+ subscribe(room, options = {}) {
6959
+ const subscriptionIds = [];
6960
+ const roomId = room.id;
6961
+ if (options.onData) {
6962
+ const dataSubId = "data_" + Date.now() + "_" + Math.random().toString(36).substr(2, 9);
6963
+ if (!this.subscriptions.data[roomId]) {
6964
+ this.subscriptions.data[roomId] = [];
6965
+ }
6966
+ this.subscriptions.data[roomId].push(options.onData);
6967
+ subscriptionIds.push({
6968
+ type: "data",
6969
+ id: dataSubId,
6970
+ callback: options.onData
6971
+ });
6604
6972
  }
6605
- const opts = options;
6606
- if (typeof opts.onUpdate !== "function") {
6607
- throw new Error("Simulation subscribe requires an onUpdate callback");
6973
+ if (options.onMessages) {
6974
+ const msgSubId = "messages_" + Date.now() + "_" + Math.random().toString(36).substr(2, 9);
6975
+ if (!this.subscriptions.messages[roomId]) {
6976
+ this.subscriptions.messages[roomId] = [];
6977
+ }
6978
+ this.subscriptions.messages[roomId].push(options.onMessages);
6979
+ subscriptionIds.push({
6980
+ type: "messages",
6981
+ id: msgSubId,
6982
+ callback: options.onMessages
6983
+ });
6608
6984
  }
6609
- const hasFilter = Array.isArray(opts.entities) && opts.entities.length > 0 || Array.isArray(opts.tags) && opts.tags.length > 0 || Boolean(opts.activeRuns);
6610
- if (!hasFilter) {
6611
- throw new Error(
6612
- "Simulation subscribe requires at least one filter (entities, tags, activeRuns)"
6613
- );
6985
+ if (options.onMoves || options.onGameEvents) {
6986
+ const handler = options.onMoves || options.onGameEvents;
6987
+ if (handler) {
6988
+ const gameSubId = "game_" + Date.now() + "_" + Math.random().toString(36).substr(2, 9);
6989
+ if (!this.subscriptions.gameEvents[roomId]) {
6990
+ this.subscriptions.gameEvents[roomId] = [];
6991
+ }
6992
+ this.subscriptions.gameEvents[roomId].push(handler);
6993
+ subscriptionIds.push({
6994
+ type: "gameEvents",
6995
+ id: gameSubId,
6996
+ callback: handler
6997
+ });
6998
+ }
6999
+ }
7000
+ const needsSubscription = subscriptionIds.length > 0 && (this.subscriptions.data[roomId]?.length ?? 0) <= 1 && (this.subscriptions.messages[roomId]?.length ?? 0) <= 1 && (this.subscriptions.gameEvents[roomId]?.length ?? 0) <= 1;
7001
+ if (needsSubscription) {
7002
+ this.rpcClient.call("H5_ROOM_SUBSCRIBE" /* H5_ROOM_SUBSCRIBE */, {
7003
+ roomId,
7004
+ subscribeToData: !!options.onData,
7005
+ subscribeToMessages: !!options.onMessages,
7006
+ subscribeToProposedMoves: !!(options.onMoves || options.onGameEvents)
7007
+ }).catch((error) => {
7008
+ console.error("Failed to set up room subscription:", error);
7009
+ });
6614
7010
  }
7011
+ let called = false;
7012
+ return () => {
7013
+ if (called) return;
7014
+ called = true;
7015
+ subscriptionIds.forEach((sub) => {
7016
+ const bucket = this.subscriptions[sub.type];
7017
+ const callbacks = bucket && bucket[roomId] || [];
7018
+ const index = callbacks.indexOf(sub.callback);
7019
+ if (index > -1) callbacks.splice(index, 1);
7020
+ });
7021
+ const hasNoCallbacks = (this.subscriptions.data[roomId]?.length ?? 0) === 0 && (this.subscriptions.messages[roomId]?.length ?? 0) === 0 && (this.subscriptions.gameEvents[roomId]?.length ?? 0) === 0;
7022
+ if (hasNoCallbacks) {
7023
+ this.rpcClient.call("H5_ROOM_UNSUBSCRIBE" /* H5_ROOM_UNSUBSCRIBE */, {
7024
+ roomId
7025
+ }).catch((error) => {
7026
+ console.error("Failed to clean up room subscription:", error);
7027
+ });
7028
+ }
7029
+ };
6615
7030
  }
6616
7031
  };
6617
7032
 
6618
- // src/simulation/index.ts
6619
- function initializeSimulation(venusApi, host) {
6620
- venusApi.simulation = {
6621
- isEnabled: () => true
6622
- };
6623
- venusApi.simulation.getConfigAsync = () => {
6624
- return host.simulation.getConfigAsync();
6625
- };
6626
- venusApi.simulation.getStateAsync = (roomId) => {
6627
- return host.simulation.getStateAsync(roomId);
6628
- };
6629
- venusApi.simulation.executeRecipeAsync = (recipeId, inputs, options) => {
6630
- return host.simulation.executeRecipeAsync(recipeId, inputs, options);
6631
- };
6632
- venusApi.simulation.getActiveRunsAsync = () => {
6633
- return host.simulation.getActiveRunsAsync();
6634
- };
6635
- venusApi.simulation.collectRecipeAsync = (runId) => {
6636
- return host.simulation.collectRecipeAsync(runId);
6637
- };
6638
- venusApi.simulation.executeScopedRecipeAsync = (recipeId, entity, inputs, options) => {
6639
- return host.simulation.executeScopedRecipeAsync(recipeId, entity, inputs, options);
6640
- };
6641
- venusApi.simulation.triggerRecipeChainAsync = (recipeId, options) => {
6642
- return host.simulation.triggerRecipeChainAsync(recipeId, options);
6643
- };
6644
- venusApi.simulation.getAvailableRecipesAsync = async (options) => {
6645
- return host.simulation.getAvailableRecipesAsync(options);
6646
- };
6647
- venusApi.simulation.getRecipeRequirementsAsync = (recipe) => {
6648
- return host.simulation.getRecipeRequirementsAsync(recipe);
6649
- };
6650
- venusApi.simulation.getBatchRecipeRequirementsAsync = (recipes) => {
6651
- return host.simulation.getBatchRecipeRequirementsAsync(recipes);
6652
- };
6653
- venusApi.simulation.resolveFieldValueAsync = (entityId, fieldPath, entity) => {
6654
- return host.simulation.resolveFieldValueAsync(entityId, fieldPath, entity);
6655
- };
6656
- venusApi.simulation.getEntityMetadataAsync = (entityId) => {
6657
- return host.simulation.getEntityMetadataAsync(entityId);
6658
- };
6659
- venusApi.simulation.getSlotAssignmentsAsync = (containerId) => {
6660
- return host.simulation.getSlotAssignmentsAsync(containerId);
6661
- };
6662
- venusApi.simulation.getSlotContainersAsync = () => {
6663
- return host.simulation.getSlotContainersAsync();
6664
- };
6665
- venusApi.simulation.assignItemToSlotAsync = (containerId, slotId, itemId) => {
6666
- return host.simulation.assignItemToSlotAsync(containerId, slotId, itemId);
6667
- };
6668
- venusApi.simulation.removeItemFromSlotAsync = (containerId, slotId) => {
6669
- return host.simulation.removeItemFromSlotAsync(containerId, slotId);
6670
- };
6671
- venusApi.simulation.getAvailableItemsAsync = (containerId, slotId) => {
6672
- return host.simulation.getAvailableItemsAsync(containerId, slotId);
6673
- };
6674
- venusApi.simulation.calculatePowerPreviewAsync = (containerId, slotId, candidateItemId) => {
6675
- return host.simulation.calculatePowerPreviewAsync(
6676
- containerId,
6677
- slotId,
6678
- candidateItemId
6679
- );
6680
- };
6681
- venusApi.simulation.executeBatchOperationsAsync = (operations, validateOnly) => {
6682
- return host.simulation.executeBatchOperationsAsync(operations, validateOnly);
6683
- };
6684
- venusApi.simulation.validateSlotAssignmentAsync = (containerId, slotId, itemId) => {
6685
- return host.simulation.validateSlotAssignmentAsync(
6686
- containerId,
6687
- slotId,
6688
- itemId
6689
- );
6690
- };
6691
- }
6692
-
6693
7033
  // src/social/RpcSocialApi.ts
6694
7034
  var RpcSocialApi = class {
6695
7035
  constructor(rpcClient) {
@@ -6736,9 +7076,9 @@ var RemoteHost = class {
6736
7076
  __publicField(this, "notifications");
6737
7077
  __publicField(this, "popups");
6738
7078
  __publicField(this, "profile");
6739
- __publicField(this, "system");
6740
7079
  __publicField(this, "cdn");
6741
7080
  __publicField(this, "time");
7081
+ __publicField(this, "post");
6742
7082
  __publicField(this, "ai");
6743
7083
  __publicField(this, "haptics");
6744
7084
  __publicField(this, "features");
@@ -6792,12 +7132,10 @@ var RemoteHost = class {
6792
7132
  this.navigation = new RpcNavigationApi(rpcClient, venusApi);
6793
7133
  this.notifications = new RpcNotificationsApi(rpcClient);
6794
7134
  this.popups = new RpcPopupsApi(rpcClient);
6795
- this.profile = new HostProfileApi(venusApi);
6796
- const deviceApi = new HostDeviceApi(venusApi);
6797
- const environmentApi = new HostEnvironmentApi(venusApi);
6798
- this.system = new HostSystemApi(deviceApi, environmentApi, venusApi);
7135
+ this.profile = new HostProfileApi();
6799
7136
  this.cdn = new HostCdnApi(getCdnBaseUrl());
6800
- this.time = new HostTimeApi(rpcClient, venusApi);
7137
+ this.time = new HostTimeApi(rpcClient);
7138
+ this.post = new RpcPostApi(rpcClient);
6801
7139
  this.ai = new RpcAiApi(rpcClient);
6802
7140
  this.haptics = new RpcHapticsApi(rpcClient);
6803
7141
  this.features = new RpcFeaturesApi(rpcClient);
@@ -6812,6 +7150,7 @@ var RemoteHost = class {
6812
7150
  venusApi.isMock = () => false;
6813
7151
  this.venusApi.sharedAssets = new RpcSharedAssetsApi(rpcClient, venusApi);
6814
7152
  initializeRoomsApi(this.venusApi, this);
7153
+ console.log("[Venus SDK] Remote host created");
6815
7154
  }
6816
7155
  get isInitialized() {
6817
7156
  return this._isInitialized;
@@ -6830,27 +7169,35 @@ var RemoteHost = class {
6830
7169
  );
6831
7170
  transport.instanceId = response.instanceId;
6832
7171
  this.log(`Remote Host Initialized with id: ${transport.instanceId}`);
6833
- const profile = response.profile;
6834
- const sanitizedProfile = {
6835
- id: profile.id,
6836
- username: profile.username,
6837
- avatarUrl: profile.avatarUrl ?? null,
6838
- isAnonymous: Boolean(profile.isAnonymous)
6839
- };
6840
- this.venusApi._profileData = sanitizedProfile;
6841
- this.venusApi._deviceData = response.device;
6842
- this.venusApi._environmentData = response.environment;
6843
- this.venusApi._localeData = response.locale;
6844
- this.venusApi._languageCodeData = response.languageCode;
7172
+ if (response.profile) {
7173
+ const profile = response.profile;
7174
+ const sanitizedProfile = {
7175
+ id: profile.id,
7176
+ username: profile.username,
7177
+ avatarUrl: profile.avatarUrl ?? null,
7178
+ isAnonymous: Boolean(profile.isAnonymous)
7179
+ };
7180
+ if (typeof window !== "undefined") {
7181
+ const globalWindow = window;
7182
+ const venus = globalWindow.venus || (globalWindow.venus = {});
7183
+ venus.profile = sanitizedProfile;
7184
+ if (venus._config) {
7185
+ venus._config.profile = sanitizedProfile;
7186
+ }
7187
+ if (venus.config) {
7188
+ venus.config.profile = sanitizedProfile;
7189
+ }
7190
+ }
7191
+ }
6845
7192
  this._isInitialized = true;
6846
- this.venusApi.launchParams = response.launchParams;
7193
+ this.venusApi.launchParams = response.launchParams || {};
6847
7194
  await this.rpcClient.call("READY" /* READY */, {});
6848
- const safeArea = response.safeArea;
6849
- if (safeArea) {
6850
- this.venusApi._safeAreaData = safeArea;
7195
+ const hudInsets = response.hudInsets;
7196
+ if (hudInsets) {
7197
+ this.venusApi.config.ui.safeArea = hudInsets;
6851
7198
  }
6852
7199
  return {
6853
- safeArea,
7200
+ hudInsets,
6854
7201
  initializeAsleep: response.initializeAsleep
6855
7202
  };
6856
7203
  }
@@ -6862,14 +7209,19 @@ var RemoteHost = class {
6862
7209
  // src/Host.ts
6863
7210
  function createHost(venusApi, isMock) {
6864
7211
  if (isMock) {
7212
+ console.log("[Venus SDK] Creating Local Host");
6865
7213
  return new MockHost(venusApi);
6866
7214
  } else {
7215
+ console.log("[Venus SDK] Creating Remote Host");
6867
7216
  return new RemoteHost(venusApi);
6868
7217
  }
6869
7218
  }
6870
7219
 
7220
+ // src/venus-api/index.js
7221
+ init_rooms();
7222
+
6871
7223
  // src/version.ts
6872
- var SDK_VERSION = "3.1.2-beta.1";
7224
+ var SDK_VERSION = "3.0.4";
6873
7225
 
6874
7226
  // src/social/index.ts
6875
7227
  function initializeSocial(venusApi, host) {
@@ -6919,8 +7271,82 @@ var VenusAPI2 = class {
6919
7271
  bottom: 10,
6920
7272
  left: 0
6921
7273
  },
6922
- // NOTE: locale and languageCode are NOT part of static config
6923
- // They are delivered via INIT_SDK handshake and accessed via getLocale()/getLanguageCode()
7274
+ uiControls: {
7275
+ closeButton: { x: 16, y: 16, width: 32, height: 32 },
7276
+ menuButton: { x: window.innerWidth - 48, y: 16, width: 32, height: 32 },
7277
+ feedHeader: { x: 0, y: 0, width: window.innerWidth, height: 66 },
7278
+ playButton: {
7279
+ x: 0,
7280
+ y: window.innerHeight - 60,
7281
+ width: window.innerWidth,
7282
+ height: 60
7283
+ }
7284
+ },
7285
+ // Complete theme structure (matching createH5Theme output)
7286
+ theme: {
7287
+ background: {
7288
+ default: "#131419",
7289
+ muted: "#1b1d25",
7290
+ dark: "#0d0e11"
7291
+ },
7292
+ text: {
7293
+ primary: "#ffffff",
7294
+ muted: "#808080",
7295
+ inverted: "#000000"
7296
+ },
7297
+ theme: {
7298
+ primary: "#f6c833",
7299
+ secondary: "#6366f1",
7300
+ background: "#131419",
7301
+ border: "#262626",
7302
+ card: "#1b1d25",
7303
+ "card-glass": "rgba(27, 29, 37, 0.8)"
7304
+ },
7305
+ typography: {
7306
+ fontFamily: {
7307
+ base: "Plus Jakarta Sans, Roboto, sans-serif",
7308
+ heading: "Plus Jakarta Sans, Roboto, sans-serif",
7309
+ mono: "monospace"
7310
+ },
7311
+ fontSize: {
7312
+ "2xs": "10px",
7313
+ xs: "12px",
7314
+ sm: "14px",
7315
+ md: "16px",
7316
+ lg: "18px",
7317
+ xl: "20px",
7318
+ "2xl": "24px",
7319
+ "3xl": "30px",
7320
+ "4xl": "36px",
7321
+ "5xl": "48px",
7322
+ "6xl": "60px"
7323
+ },
7324
+ fontWeight: {
7325
+ thin: "100",
7326
+ extralight: "200",
7327
+ light: "300",
7328
+ regular: "400",
7329
+ medium: "500",
7330
+ semibold: "600",
7331
+ bold: "700",
7332
+ extrabold: "800",
7333
+ black: "900",
7334
+ extrablack: "950"
7335
+ },
7336
+ lineHeight: {
7337
+ none: "1",
7338
+ tight: "1.25",
7339
+ snug: "1.375",
7340
+ normal: "1.5",
7341
+ relaxed: "1.625",
7342
+ loose: "2"
7343
+ }
7344
+ }
7345
+ },
7346
+ // Static locale data at top level
7347
+ locale: "en-US",
7348
+ languageCode: "en",
7349
+ // Note: Profile is now separate from config and accessed via getCurrentProfile()
6924
7350
  // Complete environment info (matching buildStaticConfig)
6925
7351
  environment: {
6926
7352
  isDevelopment: true,
@@ -6974,6 +7400,12 @@ var VenusAPI2 = class {
6974
7400
  onHide: null,
6975
7401
  onShow: null
6976
7402
  },
7403
+ currentPostInteractions: {
7404
+ isLiked: false,
7405
+ isFollowing: false,
7406
+ likesCount: 42,
7407
+ commentsCount: 7
7408
+ },
6977
7409
  // Platform overrides for testing different environments
6978
7410
  platformOverrides: {
6979
7411
  isMobile: true,
@@ -6982,74 +7414,117 @@ var VenusAPI2 = class {
6982
7414
  };
6983
7415
  this._detectHostedEnvironment();
6984
7416
  this.launchParams = {};
6985
- this.config = createProxiedObject.call(this, "config", {});
6986
- const originalConfig = this.config;
6987
- this.config = new Proxy(originalConfig, {
6988
- get(target, prop) {
6989
- if (prop === "locale") {
6990
- throw new Error("Use VenusAPI.getLocale() instead.");
6991
- }
6992
- if (prop === "languageCode") {
6993
- throw new Error("Use VenusAPI.getLanguageCode() instead.");
6994
- }
6995
- if (prop === "user") {
6996
- throw new Error("Use VenusAPI.getLocale() and VenusAPI.getLanguageCode() instead.");
6997
- }
6998
- if (prop === "device") {
6999
- throw new Error("Use VenusAPI.system.getDevice() instead.");
7000
- }
7001
- if (prop === "environment") {
7002
- throw new Error("Use VenusAPI.system.getEnvironment() instead.");
7003
- }
7004
- if (prop === "profile") {
7005
- throw new Error("Use VenusAPI.getProfile() instead.");
7006
- }
7007
- if (prop === "rooms") {
7008
- throw new Error("Rooms configuration is internal. Use VenusAPI.rooms methods instead.");
7009
- }
7010
- if (prop === "ui") {
7011
- return new Proxy({}, {
7012
- get(uiTarget, uiProp) {
7013
- if (uiProp === "safeArea") {
7014
- throw new Error("Use VenusAPI.system.getSafeArea() instead.");
7015
- }
7016
- if (uiProp === "hudInsets") {
7017
- throw new Error("Use VenusAPI.system.getSafeArea() instead.");
7018
- }
7019
- if (uiProp === "controls") {
7020
- throw new Error("UI controls are no longer supported.");
7021
- }
7022
- throw new Error(`VenusAPI.config.ui.${uiProp} is not supported.`);
7023
- }
7024
- });
7025
- }
7026
- return target[prop];
7027
- },
7028
- set(target, prop, value) {
7029
- if (prop === "locale" || prop === "languageCode" || prop === "user" || prop === "device" || prop === "environment" || prop === "profile") {
7030
- throw new Error(`VenusAPI.config.${prop} cannot be set. Configuration is read-only.`);
7031
- }
7032
- if (prop === "ui") {
7033
- console.warn("[Venus SDK] Cannot set config.ui");
7034
- return true;
7417
+ this.config = createProxiedObject.call(this, "config", {
7418
+ locale: "en-US",
7419
+ languageCode: "en",
7420
+ // Note: Profile is no longer in config - use getCurrentProfile() instead
7421
+ environment: {
7422
+ isDevelopment: true,
7423
+ platform: typeof navigator !== "undefined" ? navigator.platform : "unknown",
7424
+ platformVersion: "unknown",
7425
+ browserInfo: {
7426
+ browser: "unknown",
7427
+ userAgent: typeof navigator !== "undefined" ? navigator.userAgent : "unknown",
7428
+ isMobile: true,
7429
+ isTablet: false,
7430
+ language: typeof navigator !== "undefined" ? navigator.language : "en-US"
7035
7431
  }
7036
- target[prop] = value;
7037
- return true;
7038
7432
  },
7039
- has(target, prop) {
7040
- if (prop === "ui") {
7041
- return false;
7433
+ ui: {
7434
+ controls: {
7435
+ closeButton: { x: 16, y: 16, width: 32, height: 32 },
7436
+ menuButton: {
7437
+ x: typeof window !== "undefined" ? window.innerWidth - 48 : 352,
7438
+ y: 16,
7439
+ width: 32,
7440
+ height: 32
7441
+ },
7442
+ feedHeader: {
7443
+ x: 0,
7444
+ y: 0,
7445
+ width: typeof window !== "undefined" ? window.innerWidth : 400,
7446
+ height: 66
7447
+ },
7448
+ playButton: {
7449
+ x: 0,
7450
+ y: typeof window !== "undefined" ? window.innerHeight - 60 : 740,
7451
+ width: typeof window !== "undefined" ? window.innerWidth : 400,
7452
+ height: 60
7453
+ }
7454
+ },
7455
+ safeArea: { top: 44, left: 0, right: 0, bottom: 34 },
7456
+ hudInsets: {
7457
+ preview: { top: 60, left: 0, right: 0, bottom: 40 },
7458
+ fullscreen: { top: 44, left: 0, right: 0, bottom: 34 }
7042
7459
  }
7043
- return prop in target;
7044
7460
  },
7045
- ownKeys(target) {
7046
- return Reflect.ownKeys(target).filter((key) => key !== "ui");
7461
+ device: {
7462
+ screenSize: {
7463
+ width: typeof window !== "undefined" ? window.screen?.width || 0 : 0,
7464
+ height: typeof window !== "undefined" ? window.screen?.height || 0 : 0
7465
+ },
7466
+ viewportSize: {
7467
+ width: typeof window !== "undefined" ? window.innerWidth : 0,
7468
+ height: typeof window !== "undefined" ? window.innerHeight : 0
7469
+ },
7470
+ orientation: "portrait",
7471
+ pixelRatio: typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1,
7472
+ fontScale: 1,
7473
+ deviceType: "phone",
7474
+ hapticsEnabled: false,
7475
+ haptics: { supported: false, enabled: false }
7047
7476
  },
7048
- getOwnPropertyDescriptor(target, prop) {
7049
- if (prop === "ui") {
7050
- return void 0;
7477
+ theme: {
7478
+ background: { default: "#131419", muted: "#1b1d25", dark: "#0d0e11" },
7479
+ text: { primary: "#ffffff", muted: "#808080", inverted: "#000000" },
7480
+ theme: {
7481
+ primary: "#f6c833",
7482
+ secondary: "#6366f1",
7483
+ background: "#131419",
7484
+ border: "#262626",
7485
+ card: "#1b1d25",
7486
+ "card-glass": "rgba(27, 29, 37, 0.8)"
7487
+ },
7488
+ typography: {
7489
+ fontFamily: {
7490
+ base: "Plus Jakarta Sans, Roboto, sans-serif",
7491
+ heading: "Plus Jakarta Sans, Roboto, sans-serif",
7492
+ mono: "monospace"
7493
+ },
7494
+ fontSize: {
7495
+ "2xs": "10px",
7496
+ xs: "12px",
7497
+ sm: "14px",
7498
+ md: "16px",
7499
+ lg: "18px",
7500
+ xl: "20px",
7501
+ "2xl": "24px",
7502
+ "3xl": "30px",
7503
+ "4xl": "36px",
7504
+ "5xl": "48px",
7505
+ "6xl": "60px"
7506
+ },
7507
+ fontWeight: {
7508
+ thin: "100",
7509
+ extralight: "200",
7510
+ light: "300",
7511
+ regular: "400",
7512
+ medium: "500",
7513
+ semibold: "600",
7514
+ bold: "700",
7515
+ extrabold: "800",
7516
+ black: "900",
7517
+ extrablack: "950"
7518
+ },
7519
+ lineHeight: {
7520
+ none: "1",
7521
+ tight: "1.25",
7522
+ snug: "1.375",
7523
+ normal: "1.5",
7524
+ relaxed: "1.625",
7525
+ loose: "2"
7526
+ }
7051
7527
  }
7052
- return Reflect.getOwnPropertyDescriptor(target, prop);
7053
7528
  }
7054
7529
  });
7055
7530
  const isInsideHostedEnv = this._bootstrap.isInsideHostedEnvironment;
@@ -7058,6 +7533,7 @@ var VenusAPI2 = class {
7058
7533
  initializeStorage(this, host);
7059
7534
  initializeRoomsApi(this, host);
7060
7535
  initializeAds(this, host);
7536
+ initializeTheme(this);
7061
7537
  initializePopups(this, host);
7062
7538
  initializeAnalytics(this, host);
7063
7539
  initializeIap(this, host);
@@ -7072,31 +7548,15 @@ var VenusAPI2 = class {
7072
7548
  initializeLoggingApi(this, host);
7073
7549
  const isAvatar3dDisabled = typeof window !== "undefined" && window.location.search.includes("EXPO_PUBLIC_DISABLE_3D_AVATARS=true");
7074
7550
  initializeProfile(this, host);
7075
- initializeSystem(this, host);
7076
7551
  if (!isAvatar3dDisabled) {
7077
7552
  initializeAvatar3d(this, host);
7078
7553
  }
7079
7554
  initializeStackNavigation(this, host);
7555
+ initializePost(this, host);
7080
7556
  initializeAi(this, host);
7081
7557
  initializeSimulation(this, host);
7082
7558
  initializeSocial(this, host);
7083
7559
  initializeAssetLoader(this, createProxiedMethod);
7084
- this.getLocale = () => {
7085
- if (this._localeData) {
7086
- return this._localeData;
7087
- }
7088
- if (typeof navigator !== "undefined" && navigator.language) {
7089
- return navigator.language;
7090
- }
7091
- return "en-US";
7092
- };
7093
- this.getLanguageCode = () => {
7094
- if (this._languageCodeData) {
7095
- return this._languageCodeData;
7096
- }
7097
- const locale = this.getLocale();
7098
- return locale.split("-")[0];
7099
- };
7100
7560
  }
7101
7561
  // Generate deterministic instance ID based on current page URL
7102
7562
  _generateDeterministicInstanceId() {
@@ -7133,14 +7593,21 @@ var VenusAPI2 = class {
7133
7593
  // BOOTSTRAP METHODS
7134
7594
  //---------------------------------------
7135
7595
  _detectHostedEnvironment() {
7596
+ console.log("[Venus SDK] Detecting host environment...");
7136
7597
  const isInIframe = window.self !== window.top;
7137
7598
  const hasReactNativeWebView = typeof window.ReactNativeWebView !== "undefined";
7138
7599
  this._bootstrap.isInsideHostedEnvironment = isInIframe || hasReactNativeWebView;
7600
+ console.log(
7601
+ `[Venus SDK] isInIframe: ${isInIframe}, hasReactNativeWebView: ${hasReactNativeWebView}`
7602
+ );
7603
+ }
7604
+ isMobile() {
7605
+ return typeof window.ReactNativeWebView !== "undefined";
7139
7606
  }
7140
7607
  _initializeMockMode() {
7141
7608
  if (this._mock.localeOverride) {
7142
- this._localeData = this._mock.localeOverride;
7143
- this._languageCodeData = this._mock.localeOverride.split("-")[0];
7609
+ this.config.locale = this._mock.localeOverride;
7610
+ this.config.languageCode = this._mock.localeOverride.split("-")[0];
7144
7611
  }
7145
7612
  if (this._mock.roomsData) {
7146
7613
  console.warn(
@@ -7160,10 +7627,6 @@ var VenusAPI2 = class {
7160
7627
  }
7161
7628
  this._shared.initPromise = new Promise(async (resolve, reject) => {
7162
7629
  try {
7163
- if (this.isMock() && options?.mock) {
7164
- Object.assign(this._mock, options.mock);
7165
- console.log("[VenusAPI] Mock options applied:", options.mock);
7166
- }
7167
7630
  const result = await this.host.initialize(options);
7168
7631
  this._shared.initialized = true;
7169
7632
  if (!options || !options.usePreloader) {
@@ -7191,6 +7654,7 @@ instance.isAvailable = function() {
7191
7654
  (async () => {
7192
7655
  try {
7193
7656
  await initializeNumbers(instance);
7657
+ console.log("[Venus SDK] Numbers system initialized");
7194
7658
  } catch (error) {
7195
7659
  console.error("[Venus SDK] Failed to initialize numbers system:", error);
7196
7660
  }