@series-inc/venus-sdk 3.0.4 → 3.0.6

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.
@@ -1,9 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __hasOwnProp = Object.prototype.hasOwnProperty;
7
5
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
6
  var __esm = (fn, res) => function __init() {
9
7
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
@@ -12,15 +10,6 @@ var __export = (target, all) => {
12
10
  for (var name in all)
13
11
  __defProp(target, name, { get: all[name], enumerable: true });
14
12
  };
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);
24
13
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
25
14
 
26
15
  // src/venus-api/systems/core.js
@@ -111,221 +100,6 @@ var init_core = __esm({
111
100
  }
112
101
  });
113
102
 
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
-
329
103
  // src/storage/MockStorageApi.ts
330
104
  function createMockStorageApi(storageType, appUrl) {
331
105
  const appIdentifier = appUrl ? generateAppIdentifier(appUrl) : null;
@@ -635,190 +409,6 @@ function initializeAds(venusApiInstance, host) {
635
409
  venusApiInstance.ads = host.ads;
636
410
  }
637
411
 
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
-
822
412
  // src/popups/RpcPopupsApi.ts
823
413
  var RpcPopupsApi = class {
824
414
  constructor(rpcClient) {
@@ -971,13 +561,8 @@ var MockNotificationsApi = class {
971
561
  async cancelNotification(notificationId) {
972
562
  const venusApi = this.venusApi;
973
563
  if (isWebPlatform()) {
974
- console.log(
975
- "[Venus Mock] Cancel notification on web platform (simulated):",
976
- notificationId
977
- );
978
564
  return true;
979
565
  }
980
- console.log("[Venus Mock] Cancel local notification:", notificationId);
981
566
  await createMockDelay(MOCK_DELAYS.short);
982
567
  if (venusApi._mock.scheduledNotifications && venusApi._mock.scheduledNotifications[notificationId]) {
983
568
  delete venusApi._mock.scheduledNotifications[notificationId];
@@ -987,12 +572,8 @@ var MockNotificationsApi = class {
987
572
  }
988
573
  async getAllScheduledLocalNotifications() {
989
574
  if (isWebPlatform()) {
990
- console.log(
991
- "[Venus Mock] Get notifications on web platform (returning empty list)"
992
- );
993
575
  return [];
994
576
  }
995
- console.log("[Venus Mock] Get all scheduled local notifications");
996
577
  await createMockDelay(MOCK_DELAYS.short);
997
578
  const venusApi = this.venusApi;
998
579
  const notifications = venusApi._mock.scheduledNotifications || {};
@@ -1000,10 +581,8 @@ var MockNotificationsApi = class {
1000
581
  }
1001
582
  async isLocalNotificationsEnabled() {
1002
583
  if (isWebPlatform()) {
1003
- console.log("[Venus Mock] Notifications not available on web platform");
1004
584
  return false;
1005
585
  }
1006
- console.log("[Venus Mock] Check if local notifications are enabled");
1007
586
  await createMockDelay(MOCK_DELAYS.short);
1008
587
  const venusApi = this.venusApi;
1009
588
  const isEnabled = venusApi._mock.notificationsEnabled !== false;
@@ -1012,9 +591,6 @@ var MockNotificationsApi = class {
1012
591
  async scheduleAsync(title, body, seconds, notificationId, options) {
1013
592
  const { priority = 50, groupId, payload } = options || {};
1014
593
  if (isWebPlatform()) {
1015
- console.log(
1016
- "[Venus Mock] Notifications not supported on web platform, simulating success"
1017
- );
1018
594
  console.info(
1019
595
  "\u{1F514} [Venus Mock] Notification would be scheduled:",
1020
596
  title || "Untitled",
@@ -1025,14 +601,11 @@ var MockNotificationsApi = class {
1025
601
  const mockId = `mock-web-notification-${Date.now()}`;
1026
602
  return mockId;
1027
603
  }
1028
- console.log("[Venus Mock] Schedule local notification:", { title, body, seconds, options });
1029
604
  const venusApi = this.venusApi;
1030
605
  if (!venusApi._mock.pendingRequests) {
1031
- console.log("[Venus Mock] Initializing pendingRequests");
1032
606
  venusApi._mock.pendingRequests = {};
1033
607
  }
1034
608
  const requestId = Date.now().toString();
1035
- console.log("[Venus Mock] Creating request with ID:", requestId);
1036
609
  return new Promise((resolve) => {
1037
610
  venusApi._mock.pendingRequests[requestId] = { resolve };
1038
611
  const id = notificationId || `mock-notification-${Date.now()}`;
@@ -1054,13 +627,8 @@ var MockNotificationsApi = class {
1054
627
  async setLocalNotificationsEnabled(enabled) {
1055
628
  const venusApi = this.venusApi;
1056
629
  if (isWebPlatform()) {
1057
- console.log(
1058
- "[Venus Mock] Set notifications enabled on web platform (simulated):",
1059
- enabled
1060
- );
1061
630
  return true;
1062
631
  }
1063
- console.log("[Venus Mock] Set local notifications enabled:", enabled);
1064
632
  await createMockDelay(MOCK_DELAYS.short);
1065
633
  venusApi._mock.notificationsEnabled = enabled;
1066
634
  return enabled;
@@ -1157,9 +725,11 @@ function isPacificDaylightTime(date) {
1157
725
 
1158
726
  // src/time/HostTimeApi.ts
1159
727
  var HostTimeApi = class {
1160
- constructor(rpcClient) {
728
+ constructor(rpcClient, venusApi) {
1161
729
  __publicField(this, "rpcClient");
730
+ __publicField(this, "venusApi");
1162
731
  this.rpcClient = rpcClient;
732
+ this.venusApi = venusApi;
1163
733
  }
1164
734
  async requestTimeAsync() {
1165
735
  const response = await this.rpcClient.call(
@@ -1169,13 +739,7 @@ var HostTimeApi = class {
1169
739
  return response;
1170
740
  }
1171
741
  formatTime(timestamp, options) {
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
- }
742
+ const locale = this.venusApi.getLocale();
1179
743
  const date = new Date(timestamp);
1180
744
  const dateTimeOptions = {
1181
745
  dateStyle: options.dateStyle || "medium",
@@ -1187,13 +751,7 @@ var HostTimeApi = class {
1187
751
  }
1188
752
  formatNumber(value, options) {
1189
753
  try {
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
- }
754
+ const locale = this.venusApi.getLocale();
1197
755
  const numberOptions = {
1198
756
  style: options?.style || "decimal",
1199
757
  minimumFractionDigits: options?.minimumFractionDigits || 0,
@@ -1257,18 +815,17 @@ var MockTimeApi = class {
1257
815
  this.venusApi = venusApi;
1258
816
  }
1259
817
  formatNumber(value, options) {
1260
- const locale = this.getLocale();
818
+ const locale = this.venusApi.getLocale();
1261
819
  const numberOptions = {
1262
820
  style: options?.style || "decimal",
1263
821
  minimumFractionDigits: options?.minimumFractionDigits || 0,
1264
822
  maximumFractionDigits: options?.maximumFractionDigits || 2,
1265
823
  ...options
1266
824
  };
1267
- console.log(`[Venus Mock] Formatting number ${value} with locale ${locale}`);
1268
825
  return value.toLocaleString(locale, numberOptions);
1269
826
  }
1270
827
  formatTime(timestamp, options) {
1271
- const locale = this.getLocale();
828
+ const locale = this.venusApi.getLocale();
1272
829
  const date = new Date(timestamp);
1273
830
  const dateTimeOptions = {
1274
831
  dateStyle: options.dateStyle || "medium",
@@ -1276,13 +833,9 @@ var MockTimeApi = class {
1276
833
  hour12: options.hour12 !== void 0 ? options.hour12 : true,
1277
834
  ...options
1278
835
  };
1279
- console.log(
1280
- `[Venus Mock] Formatting time ${timestamp} with locale ${locale}`
1281
- );
1282
836
  return date.toLocaleString(locale, dateTimeOptions);
1283
837
  }
1284
838
  async getFutureTimeAsync(options) {
1285
- console.log("[Venus Mock] Getting future time with options:", options);
1286
839
  const timeInfo = await this.requestTimeAsync();
1287
840
  const serverTime = new Date(timeInfo.serverTime);
1288
841
  const result = new Date(serverTime);
@@ -1327,7 +880,6 @@ var MockTimeApi = class {
1327
880
  return result.getTime();
1328
881
  }
1329
882
  async requestTimeAsync() {
1330
- console.log("[Venus Mock] Requesting time");
1331
883
  await createMockDelay(MOCK_DELAYS.short);
1332
884
  const venusApi = this.venusApi;
1333
885
  const mockOffset = venusApi._mock.serverTimeOffset || 2500;
@@ -1341,23 +893,8 @@ var MockTimeApi = class {
1341
893
  formattedTime: new Date(localTime).toISOString(),
1342
894
  locale: venusApi._mock.user?.locale || "en-US"
1343
895
  };
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
- });
1349
896
  return timeInfo;
1350
897
  }
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
- }
1361
898
  };
1362
899
 
1363
900
  // src/time/index.ts
@@ -2206,14 +1743,11 @@ var VenusAssetLoader = class {
2206
1743
  }, 1e4);
2207
1744
  if (type === "image") {
2208
1745
  const img = new Image();
2209
- console.log(`\u{1F5BC}\uFE0F [Asset Verification] Verifying image: ${url}`);
2210
1746
  img.onload = () => {
2211
- console.log(`\u2705 [Asset Verification] Image verified successfully: ${url}`);
2212
1747
  clearTimeout(timeout);
2213
1748
  resolve();
2214
1749
  };
2215
1750
  img.onerror = (error) => {
2216
- console.log(`\u274C [Asset Verification] Image verification failed: ${url}`, error);
2217
1751
  clearTimeout(timeout);
2218
1752
  reject(new Error("Failed to load image"));
2219
1753
  };
@@ -2265,7 +1799,6 @@ var VenusAssetLoader = class {
2265
1799
  const CDN_BASE_URL = "https://venus-static-01293ak.web.app/";
2266
1800
  const cleanUrl = url.startsWith("/") ? url.slice(1) : url;
2267
1801
  const fullUrl = CDN_BASE_URL + cleanUrl;
2268
- console.log(`\u{1F310} [Asset Loader] Force remote CDN: ${url} -> ${fullUrl}`);
2269
1802
  return fullUrl;
2270
1803
  }
2271
1804
  if (this.venusAPI && this.venusAPI.isMock && this.venusAPI.isMock()) {
@@ -3976,47 +3509,105 @@ function initializeIap(venusApiInstance, host) {
3976
3509
  venusApiInstance.iap = host.iap;
3977
3510
  }
3978
3511
 
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
+
3979
3531
  // src/leaderboard/RpcLeaderboardApi.ts
3980
3532
  var RpcLeaderboardApi = class {
3981
3533
  constructor(rpcClient) {
3982
3534
  __publicField(this, "rpcClient");
3535
+ /** Cache of score tokens for automatic hash computation */
3536
+ __publicField(this, "tokenCache", /* @__PURE__ */ new Map());
3983
3537
  this.rpcClient = rpcClient;
3984
3538
  }
3985
- startRun(mode) {
3986
- return this.rpcClient.call(
3987
- "H5_LEADERBOARD_START_RUN" /* H5_LEADERBOARD_START_RUN */,
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 */,
3988
3549
  mode ? { mode } : {}
3989
3550
  );
3551
+ this.tokenCache.set(token.token, token);
3552
+ return token;
3990
3553
  }
3991
- submitScore(sessionId, score, durationSec, options) {
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
+ }
3992
3582
  return this.rpcClient.call(
3993
3583
  "H5_LEADERBOARD_SUBMIT_SCORE" /* H5_LEADERBOARD_SUBMIT_SCORE */,
3994
3584
  {
3995
- sessionId,
3996
- score,
3997
- durationSec,
3998
- mode: options?.mode,
3999
- telemetry: options?.telemetry,
4000
- metadata: options?.metadata,
4001
- hash: options?.hash
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
4002
3593
  }
4003
3594
  );
4004
3595
  }
4005
- getLeaderboard(options) {
3596
+ getPagedScores(options) {
4006
3597
  return this.rpcClient.call(
4007
- "H5_LEADERBOARD_GET" /* H5_LEADERBOARD_GET */,
3598
+ "H5_LEADERBOARD_GET_PAGED_SCORES" /* H5_LEADERBOARD_GET_PAGED_SCORES */,
4008
3599
  options ?? {}
4009
3600
  );
4010
3601
  }
4011
- getPlayerStats(options) {
3602
+ getMyRank(options) {
4012
3603
  return this.rpcClient.call(
4013
- "H5_LEADERBOARD_GET_PLAYER_STATS" /* H5_LEADERBOARD_GET_PLAYER_STATS */,
3604
+ "H5_LEADERBOARD_GET_MY_RANK" /* H5_LEADERBOARD_GET_MY_RANK */,
4014
3605
  options ?? {}
4015
3606
  );
4016
3607
  }
4017
- getLeaderboardHighlight(options) {
3608
+ getPodiumScores(options) {
4018
3609
  return this.rpcClient.call(
4019
- "H5_LEADERBOARD_GET_HIGHLIGHT" /* H5_LEADERBOARD_GET_HIGHLIGHT */,
3610
+ "H5_LEADERBOARD_GET_PODIUM_SCORES" /* H5_LEADERBOARD_GET_PODIUM_SCORES */,
4020
3611
  options ?? {}
4021
3612
  );
4022
3613
  }
@@ -4025,17 +3616,31 @@ var RpcLeaderboardApi = class {
4025
3616
  // src/leaderboard/MockLeaderboardApi.ts
4026
3617
  var MockLeaderboardApi = class {
4027
3618
  constructor(options) {
4028
- __publicField(this, "sessions", /* @__PURE__ */ new Map());
3619
+ __publicField(this, "tokens", /* @__PURE__ */ new Map());
3620
+ /** Cache of score tokens for automatic hash computation */
3621
+ __publicField(this, "tokenCache", /* @__PURE__ */ new Map());
4029
3622
  __publicField(this, "entriesByMode", /* @__PURE__ */ new Map());
4030
- __publicField(this, "sessionCounter", 0);
4031
- __publicField(this, "requiresHash", false);
4032
- if (options?.requiresHash) {
4033
- this.requiresHash = true;
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;
4034
3631
  }
4035
3632
  }
3633
+ /**
3634
+ * Configure mock leaderboard settings
3635
+ *
3636
+ * @param options - Configuration options
3637
+ */
4036
3638
  configure(options) {
4037
- if (typeof options.requiresHash === "boolean") {
4038
- this.requiresHash = options.requiresHash;
3639
+ if (typeof options.enableScoreSealing === "boolean") {
3640
+ this.enableScoreSealing = options.enableScoreSealing;
3641
+ }
3642
+ if (options.scoreSealingSecret) {
3643
+ this.scoreSealingSecret = options.scoreSealingSecret;
4039
3644
  }
4040
3645
  }
4041
3646
  generateNonce() {
@@ -4052,83 +3657,149 @@ var MockLeaderboardApi = class {
4052
3657
  }
4053
3658
  return this.entriesByMode.get(key);
4054
3659
  }
4055
- async startRun(mode) {
4056
- const sessionId = `mock_session_${++this.sessionCounter}`;
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}`;
4057
3669
  const startTime = Date.now();
4058
3670
  const expiresAt = startTime + 36e5;
4059
3671
  const resolvedMode = mode || "default";
4060
- const hashNonce = this.requiresHash ? this.generateNonce() : null;
4061
- this.sessions.set(sessionId, {
4062
- id: sessionId,
3672
+ const sealingNonce = this.enableScoreSealing ? this.generateNonce() : null;
3673
+ const sealingSecret = this.enableScoreSealing ? this.scoreSealingSecret : null;
3674
+ this.tokens.set(token, {
3675
+ id: token,
4063
3676
  expiresAt,
4064
3677
  mode: resolvedMode,
4065
- hashNonce,
3678
+ sealingNonce,
4066
3679
  used: false
4067
3680
  });
4068
- return {
4069
- sessionId,
3681
+ const result = {
3682
+ token,
4070
3683
  startTime,
4071
3684
  expiresAt,
4072
- hashNonce,
3685
+ sealingNonce,
3686
+ sealingSecret,
4073
3687
  mode: resolvedMode
4074
3688
  };
3689
+ this.tokenCache.set(token, result);
3690
+ return result;
4075
3691
  }
4076
- async submitScore(sessionId, score, durationSec, options) {
4077
- const session = this.sessions.get(sessionId);
4078
- if (!session) {
4079
- throw new Error("Invalid leaderboard session");
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");
4080
3755
  }
4081
- if (session.expiresAt < Date.now()) {
4082
- throw new Error("Invalid or expired leaderboard session");
3756
+ if (scoreToken.expiresAt < Date.now()) {
3757
+ throw new Error("Invalid or expired score token");
4083
3758
  }
4084
- if (session.used) {
4085
- throw new Error("Leaderboard session already used");
3759
+ if (scoreToken.used) {
3760
+ throw new Error("Score token already used");
4086
3761
  }
4087
- if (options?.mode && options.mode !== session.mode) {
4088
- throw new Error("Submission mode does not match session mode");
3762
+ if (params.mode && params.mode !== scoreToken.mode) {
3763
+ throw new Error("Submission mode does not match token mode");
4089
3764
  }
4090
- if (session.hashNonce && !options?.hash) {
4091
- throw new Error("Score hash is required for sealed leaderboard submissions");
3765
+ if (scoreToken.sealingNonce && !hash) {
3766
+ throw new Error("Score hash required when score sealing is enabled");
4092
3767
  }
4093
3768
  const submittedAt = Date.now();
4094
3769
  const entry = {
4095
3770
  profileId: `mock_profile`,
4096
3771
  username: "Mock Player",
4097
3772
  avatarUrl: null,
4098
- score,
4099
- durationSec,
3773
+ score: params.score,
3774
+ duration: params.duration,
4100
3775
  submittedAt,
4101
- sessionId,
3776
+ token: params.token,
4102
3777
  rank: null,
4103
3778
  zScore: null,
4104
3779
  isAnomaly: false,
4105
3780
  trustScore: 50,
4106
- metadata: options?.metadata ?? null,
3781
+ metadata: params.metadata ?? null,
4107
3782
  isSeed: false
4108
3783
  };
4109
- const modeEntries = this.getEntriesForMode(session.mode);
3784
+ const modeEntries = this.getEntriesForMode(scoreToken.mode);
4110
3785
  modeEntries.push(entry);
4111
3786
  modeEntries.sort((a, b) => {
4112
- if (b.score !== a.score) {
4113
- return b.score - a.score;
4114
- }
3787
+ if (b.score !== a.score) return b.score - a.score;
4115
3788
  return a.submittedAt - b.submittedAt;
4116
3789
  });
4117
3790
  modeEntries.forEach((e, index) => {
4118
- modeEntries[index] = {
4119
- ...e,
4120
- rank: index + 1
4121
- };
3791
+ modeEntries[index] = { ...e, rank: index + 1 };
4122
3792
  });
4123
- session.used = true;
4124
- session.hashNonce = null;
4125
- const inserted = modeEntries.find((e) => e.sessionId === sessionId && e.submittedAt === submittedAt);
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);
4126
3797
  return {
4127
3798
  accepted: true,
4128
3799
  rank: inserted?.rank ?? null
4129
3800
  };
4130
3801
  }
4131
- async getLeaderboard(options) {
3802
+ async getPagedScores(options) {
4132
3803
  const limit = options?.limit ?? 10;
4133
3804
  const mode = options?.mode ?? "default";
4134
3805
  const modeEntries = [...this.getEntriesForMode(mode)];
@@ -4144,7 +3815,7 @@ var MockLeaderboardApi = class {
4144
3815
  periodInstance: options?.period ?? "alltime"
4145
3816
  };
4146
3817
  }
4147
- async getPlayerStats(_options) {
3818
+ async getMyRank(_options) {
4148
3819
  const mode = _options?.mode ?? "default";
4149
3820
  const modeEntries = this.getEntriesForMode(mode);
4150
3821
  const playerEntry = modeEntries[0] ?? null;
@@ -4157,7 +3828,7 @@ var MockLeaderboardApi = class {
4157
3828
  periodInstance: _options?.period ?? "alltime"
4158
3829
  };
4159
3830
  }
4160
- async getLeaderboardHighlight(options) {
3831
+ async getPodiumScores(options) {
4161
3832
  const mode = options?.mode ?? "default";
4162
3833
  const modeEntries = [...this.getEntriesForMode(mode)];
4163
3834
  const topCount = Math.max(1, Math.min(options?.topCount ?? 3, 10));
@@ -4503,7 +4174,6 @@ var MockPostApi = class {
4503
4174
  }
4504
4175
  async toggleFollowAsync() {
4505
4176
  const venusApi = this.venusApi;
4506
- console.log("[Venus Mock] *Toggling follow status");
4507
4177
  await createMockDelay(MOCK_DELAYS.short);
4508
4178
  venusApi._mock.currentPostInteractions.isFollowing = !venusApi._mock.currentPostInteractions.isFollowing;
4509
4179
  const isFollowing = venusApi._mock.currentPostInteractions.isFollowing;
@@ -4762,870 +4432,425 @@ function initializeLifecycleApi(venusApi, host) {
4762
4432
  venusApi.lifecycles = host.lifecycle;
4763
4433
  }
4764
4434
 
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;
4772
- }
4435
+ // src/rooms/VenusRoom.ts
4436
+ var VenusRoom = class {
4437
+ constructor(roomData) {
4438
+ __publicField(this, "id");
4439
+ __publicField(this, "name");
4440
+ __publicField(this, "players");
4441
+ __publicField(this, "maxPlayers");
4442
+ __publicField(this, "gameType");
4443
+ __publicField(this, "appId");
4444
+ __publicField(this, "type");
4445
+ __publicField(this, "createdBy");
4446
+ __publicField(this, "createdAt");
4447
+ __publicField(this, "updatedAt");
4448
+ __publicField(this, "isPrivate");
4449
+ __publicField(this, "status");
4450
+ __publicField(this, "customMetadata");
4451
+ __publicField(this, "admins");
4452
+ __publicField(this, "roomCode");
4453
+ __publicField(this, "description");
4454
+ __publicField(this, "data");
4455
+ __publicField(this, "version");
4456
+ this.id = roomData.id;
4457
+ this.name = roomData.name;
4458
+ this.players = Array.isArray(roomData.currentPlayers) ? [...roomData.currentPlayers] : [];
4459
+ this.maxPlayers = roomData.maxPlayers;
4460
+ this.gameType = roomData.gameType;
4461
+ this.appId = roomData.appId;
4462
+ this.type = roomData.type;
4463
+ this.createdBy = roomData.createdBy;
4464
+ this.createdAt = roomData.createdAt;
4465
+ this.updatedAt = roomData.updatedAt;
4466
+ this.isPrivate = roomData.isPrivate;
4467
+ this.status = roomData.status;
4468
+ this.customMetadata = roomData.customMetadata || {};
4469
+ this.admins = Array.isArray(roomData.admins) ? [...roomData.admins] : [];
4470
+ this.roomCode = roomData.roomCode;
4471
+ this.description = roomData.description;
4472
+ this.data = roomData.data || {};
4473
+ this.version = roomData.version;
4773
4474
  }
4774
- return totals;
4475
+ };
4476
+
4477
+ // src/rooms/setupRoomNotifications.ts
4478
+ function invokeCallbacks(callbacks, event, context) {
4479
+ callbacks.forEach((callback) => {
4480
+ try {
4481
+ callback(event);
4482
+ } catch (error) {
4483
+ console.error(`[Venus SDK] Error in ${context} callback:`, error);
4484
+ throw error;
4485
+ }
4486
+ });
4487
+ }
4488
+ function setupRoomNotifications(transport, getSubscriptions) {
4489
+ return transport.onVenusMessage((message) => {
4490
+ const subscriptions = getSubscriptions();
4491
+ if (!subscriptions) {
4492
+ return;
4493
+ }
4494
+ if (message.type === "H5_ROOM_DATA_UPDATED") {
4495
+ const messageData = message.data;
4496
+ const { roomId, roomData } = messageData;
4497
+ if (!roomId) return;
4498
+ const callbacks = subscriptions.data[roomId] || [];
4499
+ const event = {
4500
+ type: "H5_ROOM_DATA_UPDATED",
4501
+ roomId,
4502
+ roomData,
4503
+ timestamp: messageData.timestamp
4504
+ };
4505
+ invokeCallbacks(callbacks, event, "room data");
4506
+ }
4507
+ if (message.type === "H5_ROOM_MESSAGE_RECEIVED" || message.type === "H5_ROOM_MESSAGE_UPDATED" || message.type === "H5_ROOM_MESSAGE_DELETED") {
4508
+ const messageData = message.data;
4509
+ const { roomId } = messageData;
4510
+ if (!roomId) return;
4511
+ const callbacks = subscriptions.messages[roomId] || [];
4512
+ const event = {
4513
+ type: message.type,
4514
+ roomId,
4515
+ message: messageData.message,
4516
+ timestamp: messageData.timestamp
4517
+ };
4518
+ invokeCallbacks(callbacks, event, "room message");
4519
+ }
4520
+ if (message.type === "app:h5:proposedMoveValidationUpdated") {
4521
+ const messageData = message.data;
4522
+ const { roomId } = messageData;
4523
+ if (!roomId) return;
4524
+ const callbacks = subscriptions.gameEvents[roomId] || [];
4525
+ const event = {
4526
+ type: "app:h5:proposedMoveValidationUpdated",
4527
+ roomId,
4528
+ proposedMoveData: messageData.proposedMoveData,
4529
+ proposedMoveId: messageData.proposedMoveId,
4530
+ changeType: messageData.changeType,
4531
+ timestamp: messageData.timestamp
4532
+ };
4533
+ invokeCallbacks(callbacks, event, "game event");
4534
+ }
4535
+ });
4775
4536
  }
4776
4537
 
4777
- // src/simulation/RpcSimulationApi.ts
4778
- var RpcSimulationApi = class {
4538
+ // src/rooms/RpcRoomsApi.ts
4539
+ var RpcRoomsApi = class {
4779
4540
  constructor(rpcClient) {
4780
4541
  __publicField(this, "rpcClient");
4781
- __publicField(this, "_simulationConfig", null);
4542
+ __publicField(this, "subscriptions");
4782
4543
  this.rpcClient = rpcClient;
4544
+ this.subscriptions = {
4545
+ data: {},
4546
+ messages: {},
4547
+ gameEvents: {}
4548
+ };
4783
4549
  }
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
- );
4793
- }
4794
- sumContributions(contributions) {
4795
- return sumContributions(contributions);
4550
+ /**
4551
+ * Get the subscription state for external access (used by setupRoomNotifications)
4552
+ */
4553
+ getSubscriptions() {
4554
+ return this.subscriptions;
4796
4555
  }
4797
- executeBatchOperationsAsync(operations, validateOnly) {
4798
- return this.rpcClient.call("H5_SIMULATION_BATCH_OPERATIONS" /* H5_SIMULATION_BATCH_OPERATIONS */, {
4799
- operations,
4800
- validateOnly
4801
- });
4556
+ /**
4557
+ * Set up room notification routing from the transport
4558
+ */
4559
+ setupNotifications(transport) {
4560
+ setupRoomNotifications(transport, () => this.getSubscriptions());
4802
4561
  }
4803
- async getAvailableItemsAsync(containerId, slotId) {
4562
+ async createRoomAsync(options) {
4804
4563
  const response = await this.rpcClient.call(
4805
- "H5_SIMULATION_GET_AVAILABLE_ITEMS" /* H5_SIMULATION_GET_AVAILABLE_ITEMS */,
4564
+ "H5_ROOM_CREATE" /* H5_ROOM_CREATE */,
4806
4565
  {
4807
- containerId,
4808
- slotId
4566
+ options
4809
4567
  }
4810
4568
  );
4811
- return response.availableItems || [];
4812
- }
4813
- calculatePowerPreviewAsync(containerId, slotId, candidateItemId) {
4814
- return this.rpcClient.call(
4815
- "H5_SIMULATION_CALCULATE_POWER_PREVIEW" /* H5_SIMULATION_CALCULATE_POWER_PREVIEW */,
4816
- {
4817
- containerId,
4818
- slotId,
4819
- candidateItemId
4820
- }
4821
- );
4822
- }
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() {
4837
- const response = await this.rpcClient.call(
4838
- "H5_SIMULATION_GET_CONTAINERS" /* H5_SIMULATION_GET_CONTAINERS */,
4839
- {}
4840
- );
4841
- return response.containers || [];
4569
+ if (response.success === false) {
4570
+ const errorMessage = typeof response.error === "string" ? response.error : "Failed to create room";
4571
+ throw new Error(errorMessage);
4572
+ }
4573
+ const room = new VenusRoom(response.roomData);
4574
+ return room;
4842
4575
  }
4843
- async getSlotAssignmentsAsync(containerId) {
4576
+ async joinOrCreateRoomAsync(options) {
4844
4577
  const response = await this.rpcClient.call(
4845
- "H5_SIMULATION_GET_ASSIGNMENTS" /* H5_SIMULATION_GET_ASSIGNMENTS */,
4578
+ "H5_ROOM_JOIN_OR_CREATE" /* H5_ROOM_JOIN_OR_CREATE */,
4846
4579
  {
4847
- containerId
4580
+ options
4848
4581
  }
4849
4582
  );
4850
- return Array.isArray(response) ? response : response.assignments || [];
4583
+ if (response.success === false) {
4584
+ const errorMessage = typeof response.error === "string" ? response.error : "Failed to join or create room";
4585
+ throw new Error(errorMessage);
4586
+ }
4587
+ const room = new VenusRoom(response.value.roomData);
4588
+ return {
4589
+ action: response.value.action,
4590
+ room,
4591
+ playersJoined: response.value.playersJoined
4592
+ };
4851
4593
  }
4852
- async getStateAsync(roomId) {
4594
+ async joinRoomByCodeAsync(roomCode) {
4853
4595
  const response = await this.rpcClient.call(
4854
- "H5_SIMULATION_GET_STATE" /* H5_SIMULATION_GET_STATE */,
4596
+ "H5_ROOM_JOIN_BY_CODE" /* H5_ROOM_JOIN_BY_CODE */,
4855
4597
  {
4856
- roomId
4598
+ roomCode
4857
4599
  }
4858
4600
  );
4859
- console.log("[Venus SDK] getStateAsync", response);
4860
- if (response.configuration) {
4861
- this._simulationConfig = response.configuration;
4862
- }
4863
- return response;
4864
- }
4865
- async getConfigAsync(roomId) {
4866
- if (this._simulationConfig) {
4867
- return this._simulationConfig;
4868
- }
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;
4601
+ if (response?.success === false) {
4602
+ const errorMessage = typeof response.error === "string" ? response.error : "Failed to join room by code";
4603
+ throw new Error(errorMessage);
4877
4604
  }
4878
- throw new Error("No simulation configuration available");
4879
- }
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
- });
4605
+ const room = new VenusRoom(response.roomData);
4606
+ return room;
4899
4607
  }
4900
- executeScopedRecipeAsync(recipeId, entity, inputs, options) {
4901
- return this.rpcClient.call(
4902
- "H5_SIMULATION_EXECUTE_SCOPED_RECIPE" /* H5_SIMULATION_EXECUTE_SCOPED_RECIPE */,
4608
+ // Get user's rooms with optional filtering
4609
+ async getUserRoomsAsync(options = {}) {
4610
+ const response = await this.rpcClient.call(
4611
+ "H5_ROOM_GET_USER_ROOMS" /* H5_ROOM_GET_USER_ROOMS */,
4903
4612
  {
4904
- recipeId,
4905
- entity,
4906
- inputs,
4907
- roomId: options?.roomId ?? null,
4908
- options
4613
+ includeArchived: options.includeArchived ?? false
4909
4614
  }
4910
4615
  );
4911
- }
4912
- getAvailableRecipesAsync(options) {
4913
- return this.rpcClient.call(
4914
- "H5_SIMULATION_GET_AVAILABLE_RECIPES" /* H5_SIMULATION_GET_AVAILABLE_RECIPES */,
4915
- {
4916
- roomId: options?.roomId || null,
4917
- includeActorRecipes: options?.includeActorRecipes || false
4616
+ if (response?.success === false) {
4617
+ const errorMessage = typeof response.error === "string" ? response.error : "Failed to get user rooms";
4618
+ throw new Error(errorMessage);
4619
+ }
4620
+ const venusRooms = [];
4621
+ for (const roomData of response.rooms) {
4622
+ if (!roomData.id) {
4623
+ console.warn("[Venus SDK] getUserRooms: Skipping room with missing ID:", roomData);
4624
+ continue;
4918
4625
  }
4919
- );
4920
- }
4921
- getRecipeRequirementsAsync(recipe) {
4922
- return this.rpcClient.call(
4923
- "H5_SIMULATION_GET_RECIPE_REQUIREMENTS" /* H5_SIMULATION_GET_RECIPE_REQUIREMENTS */,
4924
- {
4925
- recipeId: recipe.recipeId,
4926
- entity: recipe.entity,
4927
- batchAmount: recipe.batchAmount
4626
+ try {
4627
+ const venusRoom = new VenusRoom(roomData);
4628
+ venusRooms.push(venusRoom);
4629
+ } catch (error) {
4630
+ console.warn(
4631
+ "[Venus SDK] getUserRooms: Failed to create VenusRoom object:",
4632
+ error,
4633
+ roomData
4634
+ );
4928
4635
  }
4929
- );
4636
+ }
4637
+ return venusRooms;
4930
4638
  }
4931
- getBatchRecipeRequirementsAsync(recipes) {
4932
- return this.rpcClient.call(
4933
- "H5_SIMULATION_GET_BATCH_RECIPE_REQUIREMENTS" /* H5_SIMULATION_GET_BATCH_RECIPE_REQUIREMENTS */,
4639
+ async updateRoomDataAsync(room, updates, options = {}) {
4640
+ const response = await this.rpcClient.call(
4641
+ "H5_ROOM_UPDATE_DATA" /* H5_ROOM_UPDATE_DATA */,
4934
4642
  {
4935
- recipes
4643
+ roomId: room.id,
4644
+ updates,
4645
+ merge: options.merge ?? true
4936
4646
  }
4937
4647
  );
4648
+ if (response?.success === false) {
4649
+ const errorMessage = typeof response.error === "string" ? response.error : "Failed to update room data";
4650
+ throw new Error(errorMessage);
4651
+ }
4938
4652
  }
4939
- triggerRecipeChainAsync(recipeId, options) {
4940
- return this.rpcClient.call(
4941
- "H5_SIMULATION_TRIGGER_RECIPE_CHAIN" /* H5_SIMULATION_TRIGGER_RECIPE_CHAIN */,
4653
+ async getRoomDataAsync(room) {
4654
+ const response = await this.rpcClient.call(
4655
+ "H5_ROOM_GET_DATA" /* H5_ROOM_GET_DATA */,
4942
4656
  {
4943
- triggerRecipeId: recipeId,
4944
- context: options?.context,
4945
- roomId: options?.roomId
4657
+ roomId: room.id
4946
4658
  }
4947
4659
  );
4660
+ if (response?.success === false) {
4661
+ const errorMessage = typeof response.error === "string" ? response.error : "Failed to get room data";
4662
+ throw new Error(errorMessage);
4663
+ }
4664
+ return response.data;
4948
4665
  }
4949
- getEntityMetadataAsync(entityId) {
4950
- return this.rpcClient.call(
4951
- "H5_SIMULATION_GET_ENTITY_METADATA" /* H5_SIMULATION_GET_ENTITY_METADATA */,
4666
+ async sendRoomMessageAsync(venusRoom, request) {
4667
+ const response = await this.rpcClient.call(
4668
+ "H5_ROOM_SEND_MESSAGE" /* H5_ROOM_SEND_MESSAGE */,
4952
4669
  {
4953
- entityId
4670
+ roomId: venusRoom.id,
4671
+ message: request.message,
4672
+ metadata: request.metadata
4954
4673
  }
4955
4674
  );
4675
+ if (response?.success === false) {
4676
+ const errorMessage = typeof response.error === "string" ? response.error : "Failed to send message";
4677
+ throw new Error(errorMessage);
4678
+ }
4679
+ return response.messageId;
4956
4680
  }
4957
- async resolveFieldValueAsync(entityId, fieldPath, entity) {
4681
+ async leaveRoomAsync(room) {
4958
4682
  const response = await this.rpcClient.call(
4959
- "H5_SIMULATION_RESOLVE_VALUE" /* H5_SIMULATION_RESOLVE_VALUE */,
4683
+ "H5_ROOM_LEAVE" /* H5_ROOM_LEAVE */,
4960
4684
  {
4961
- entityId,
4962
- fieldPath,
4963
- entity
4685
+ roomId: room.id
4964
4686
  }
4965
4687
  );
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);
5129
- }
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
- };
5176
- }
5177
- async triggerRecipeChainAsync(recipeId, options) {
5178
- this.log("triggerRecipeChainAsync called:", { recipeId, ...options });
5179
- return {
5180
- success: true,
5181
- message: "Mock recipe chain triggered successfully"
5182
- };
5183
- }
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
- }
5215
- }
5216
- }
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
- }
5223
- }
5224
- }
5225
- if (recipe.beginEffects) {
5226
- this.applyEffects(state, recipe.beginEffects);
5227
- }
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
- };
4688
+ if (response?.success === false) {
4689
+ const errorMessage = typeof response.error === "string" ? response.error : "Failed to leave room";
4690
+ throw new Error(errorMessage);
5256
4691
  }
5257
4692
  }
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);
5285
- }
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);
5327
- }
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
- }
5357
- }
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);
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);
4693
+ async startRoomGameAsync(room, options = {}) {
4694
+ const response = await this.rpcClient.call(
4695
+ "H5_ROOM_START_GAME" /* H5_ROOM_START_GAME */,
4696
+ {
4697
+ roomId: room.id,
4698
+ gameConfig: options.gameConfig ?? {},
4699
+ turnOrder: options.turnOrder ?? null
5401
4700
  }
5402
- }
5403
- console.log(
5404
- `[Venus Simulation Mock] Completed run ${runId}, outputs:`,
5405
- outputs
5406
4701
  );
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
- );
5488
- }
4702
+ if (response?.success === false) {
4703
+ const errorMessage = typeof response.error === "string" ? response.error : "Failed to start game";
4704
+ throw new Error(errorMessage);
5489
4705
  }
5490
4706
  }
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)
5515
- };
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
- }
5532
- };
5533
-
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
5610
- );
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
4707
+ async proposeMoveAsync(room, proposalPayload) {
4708
+ const response = await this.rpcClient.call(
4709
+ "h5:room:proposeMove" /* H5_ROOM_PROPOSE_MOVE */,
4710
+ {
4711
+ roomId: room.id,
4712
+ gameSpecificState: proposalPayload.gameSpecificState,
4713
+ moveType: proposalPayload.moveType,
4714
+ clientContext: proposalPayload.clientContext,
4715
+ clientProposalId: proposalPayload.clientProposalId
4716
+ }
5620
4717
  );
5621
- };
5622
- venusApi.simulation.sumContributions = (contributions) => {
5623
- return host.simulation.sumContributions(contributions);
5624
- };
5625
- }
4718
+ if (response?.success === false) {
4719
+ const errorMessage = typeof response.error === "string" ? response.error : "Failed to propose move";
4720
+ throw new Error(errorMessage);
4721
+ }
4722
+ return response.data;
4723
+ }
4724
+ async validateMoveAsync(_room, moveId, verdict) {
4725
+ return {
4726
+ success: true,
4727
+ moveId,
4728
+ isValid: verdict.isValid,
4729
+ reason: verdict.reason
4730
+ };
4731
+ }
4732
+ async subscribeAsync(room, options = {}) {
4733
+ const roomId = room.id;
4734
+ const existingData = this.subscriptions.data[roomId];
4735
+ const existingMessages = this.subscriptions.messages[roomId];
4736
+ const existingGameEvents = this.subscriptions.gameEvents[roomId];
4737
+ const subscribeToData = Boolean(options.onData) && (existingData?.length ?? 0) === 0;
4738
+ const subscribeToMessages = Boolean(options.onMessages) && (existingMessages?.length ?? 0) === 0;
4739
+ const subscribeToProposedMoves = Boolean(options.onGameEvents) && (existingGameEvents?.length ?? 0) === 0;
4740
+ if (subscribeToData || subscribeToMessages || subscribeToProposedMoves) {
4741
+ try {
4742
+ await this.rpcClient.call("H5_ROOM_SUBSCRIBE" /* H5_ROOM_SUBSCRIBE */, {
4743
+ roomId,
4744
+ subscribeToData,
4745
+ subscribeToMessages,
4746
+ subscribeToProposedMoves
4747
+ });
4748
+ } catch (error) {
4749
+ console.error("[Venus SDK] Failed to set up room subscription:", error);
4750
+ throw error;
4751
+ }
4752
+ }
4753
+ if (options.onData) {
4754
+ if (!this.subscriptions.data[roomId]) {
4755
+ this.subscriptions.data[roomId] = [];
4756
+ }
4757
+ this.subscriptions.data[roomId].push(options.onData);
4758
+ }
4759
+ if (options.onMessages) {
4760
+ if (!this.subscriptions.messages[roomId]) {
4761
+ this.subscriptions.messages[roomId] = [];
4762
+ }
4763
+ this.subscriptions.messages[roomId].push(options.onMessages);
4764
+ }
4765
+ if (options.onGameEvents) {
4766
+ if (!this.subscriptions.gameEvents[roomId]) {
4767
+ this.subscriptions.gameEvents[roomId] = [];
4768
+ }
4769
+ this.subscriptions.gameEvents[roomId].push(options.onGameEvents);
4770
+ }
4771
+ let disposed = false;
4772
+ return () => {
4773
+ if (disposed) return;
4774
+ disposed = true;
4775
+ if (options.onData) {
4776
+ const callbacks = this.subscriptions.data[roomId];
4777
+ if (callbacks) {
4778
+ const index = callbacks.indexOf(options.onData);
4779
+ if (index > -1) {
4780
+ callbacks.splice(index, 1);
4781
+ }
4782
+ }
4783
+ }
4784
+ if (options.onMessages) {
4785
+ const callbacks = this.subscriptions.messages[roomId];
4786
+ if (callbacks) {
4787
+ const index = callbacks.indexOf(options.onMessages);
4788
+ if (index > -1) {
4789
+ callbacks.splice(index, 1);
4790
+ }
4791
+ }
4792
+ }
4793
+ if (options.onGameEvents) {
4794
+ const callbacks = this.subscriptions.gameEvents[roomId];
4795
+ if (callbacks) {
4796
+ const index = callbacks.indexOf(options.onGameEvents);
4797
+ if (index > -1) {
4798
+ callbacks.splice(index, 1);
4799
+ }
4800
+ }
4801
+ }
4802
+ const hasAnySubscriptions = (this.subscriptions.data[roomId]?.length ?? 0) > 0 || (this.subscriptions.messages[roomId]?.length ?? 0) > 0 || (this.subscriptions.gameEvents[roomId]?.length ?? 0) > 0;
4803
+ if (!hasAnySubscriptions) {
4804
+ this.rpcClient.call("H5_ROOM_UNSUBSCRIBE" /* H5_ROOM_UNSUBSCRIBE */, {
4805
+ roomId
4806
+ }).catch((error) => {
4807
+ console.error("[Venus SDK] Failed to clean up room subscription:", error);
4808
+ });
4809
+ }
4810
+ };
4811
+ }
4812
+ };
5626
4813
 
5627
- // src/MockHost.ts
5628
- init_rooms();
4814
+ // src/rooms/index.ts
4815
+ function bindMethod(target, targetKey, source, sourceKey) {
4816
+ const key = sourceKey ?? targetKey;
4817
+ const fn = source?.[key];
4818
+ if (typeof fn === "function") {
4819
+ target[targetKey] = fn.bind(source);
4820
+ return true;
4821
+ }
4822
+ return false;
4823
+ }
4824
+ function initializeRoomsApi(venusApi, host) {
4825
+ const roomsApi = host?.rooms;
4826
+ if (!roomsApi) {
4827
+ console.warn(
4828
+ "[Venus SDK] Host did not provide a rooms implementation. Rooms API will be unavailable."
4829
+ );
4830
+ return;
4831
+ }
4832
+ const venus = venusApi;
4833
+ const existingNamespace = venus.rooms || {};
4834
+ const roomsNamespace = Object.assign({}, existingNamespace);
4835
+ const namespaceBindings = [
4836
+ ["createRoomAsync"],
4837
+ ["joinOrCreateRoomAsync"],
4838
+ ["joinRoomByCodeAsync"],
4839
+ ["getUserRoomsAsync"],
4840
+ ["subscribeAsync"],
4841
+ ["updateRoomDataAsync"],
4842
+ ["getRoomDataAsync"],
4843
+ ["sendRoomMessageAsync"],
4844
+ ["leaveRoomAsync"],
4845
+ ["startRoomGameAsync"],
4846
+ ["proposeMoveAsync"],
4847
+ ["validateMoveAsync"]
4848
+ ];
4849
+ namespaceBindings.forEach(([targetKey, sourceKey]) => {
4850
+ bindMethod(roomsNamespace, targetKey, roomsApi, sourceKey);
4851
+ });
4852
+ venus.rooms = roomsNamespace;
4853
+ }
5629
4854
 
5630
4855
  // src/logging/MockLoggingApi.ts
5631
4856
  var MockLoggingApi = class {
@@ -5848,44 +5073,116 @@ var ROOMS_UNAVAILABLE_MESSAGE = "[Venus SDK] Rooms API is only available when ru
5848
5073
  function createUnavailableRoomsApi() {
5849
5074
  const roomsUnavailableError = () => new Error(ROOMS_UNAVAILABLE_MESSAGE);
5850
5075
  return {
5851
- async createRoom() {
5076
+ async createRoomAsync() {
5852
5077
  throw roomsUnavailableError();
5853
5078
  },
5854
- async joinOrCreateRoom() {
5079
+ async joinOrCreateRoomAsync() {
5855
5080
  throw roomsUnavailableError();
5856
5081
  },
5857
- async getUserRooms() {
5082
+ async joinRoomByCodeAsync() {
5858
5083
  throw roomsUnavailableError();
5859
5084
  },
5860
- async joinRoomByCode() {
5085
+ async getUserRoomsAsync() {
5861
5086
  throw roomsUnavailableError();
5862
5087
  },
5863
- subscribe() {
5088
+ async subscribeAsync() {
5864
5089
  throw roomsUnavailableError();
5865
5090
  },
5866
- async updateData() {
5091
+ async updateRoomDataAsync() {
5867
5092
  throw roomsUnavailableError();
5868
5093
  },
5869
- async getData() {
5094
+ async getRoomDataAsync() {
5870
5095
  throw roomsUnavailableError();
5871
5096
  },
5872
- async sendMessage() {
5097
+ async sendRoomMessageAsync() {
5873
5098
  throw roomsUnavailableError();
5874
5099
  },
5875
- async leave() {
5100
+ async leaveRoomAsync() {
5876
5101
  throw roomsUnavailableError();
5877
5102
  },
5878
- async startGame() {
5103
+ async startRoomGameAsync() {
5879
5104
  throw roomsUnavailableError();
5880
5105
  },
5881
- async proposeMove() {
5106
+ async proposeMoveAsync() {
5882
5107
  throw roomsUnavailableError();
5883
5108
  },
5884
- async validateMove() {
5109
+ async validateMoveAsync() {
5885
5110
  throw roomsUnavailableError();
5886
5111
  }
5887
5112
  };
5888
5113
  }
5114
+ var SIMULATION_UNAVAILABLE_MESSAGE = "[Venus SDK] Simulation API is only available when running inside the Venus host environment.";
5115
+ function createUnavailableSimulationApi() {
5116
+ const simulationUnavailableError = () => new Error(SIMULATION_UNAVAILABLE_MESSAGE);
5117
+ return {
5118
+ isEnabled() {
5119
+ return false;
5120
+ },
5121
+ async getStateAsync() {
5122
+ throw simulationUnavailableError();
5123
+ },
5124
+ async getConfigAsync() {
5125
+ throw simulationUnavailableError();
5126
+ },
5127
+ async executeRecipeAsync() {
5128
+ throw simulationUnavailableError();
5129
+ },
5130
+ async getActiveRunsAsync() {
5131
+ throw simulationUnavailableError();
5132
+ },
5133
+ async collectRecipeAsync() {
5134
+ throw simulationUnavailableError();
5135
+ },
5136
+ async executeScopedRecipeAsync() {
5137
+ throw simulationUnavailableError();
5138
+ },
5139
+ async triggerRecipeChainAsync() {
5140
+ throw simulationUnavailableError();
5141
+ },
5142
+ async getAvailableRecipesAsync() {
5143
+ throw simulationUnavailableError();
5144
+ },
5145
+ async getRecipeRequirementsAsync() {
5146
+ throw simulationUnavailableError();
5147
+ },
5148
+ async getBatchRecipeRequirementsAsync() {
5149
+ throw simulationUnavailableError();
5150
+ },
5151
+ async resolveFieldValueAsync() {
5152
+ throw simulationUnavailableError();
5153
+ },
5154
+ async getEntityMetadataAsync() {
5155
+ throw simulationUnavailableError();
5156
+ },
5157
+ async getSlotContainersAsync() {
5158
+ throw simulationUnavailableError();
5159
+ },
5160
+ async getSlotAssignmentsAsync() {
5161
+ throw simulationUnavailableError();
5162
+ },
5163
+ async assignItemToSlotAsync() {
5164
+ throw simulationUnavailableError();
5165
+ },
5166
+ async removeItemFromSlotAsync() {
5167
+ throw simulationUnavailableError();
5168
+ },
5169
+ async getAvailableItemsAsync() {
5170
+ throw simulationUnavailableError();
5171
+ },
5172
+ async calculatePowerPreviewAsync() {
5173
+ throw simulationUnavailableError();
5174
+ },
5175
+ async validateSlotAssignmentAsync() {
5176
+ throw simulationUnavailableError();
5177
+ },
5178
+ async executeBatchOperationsAsync() {
5179
+ throw simulationUnavailableError();
5180
+ },
5181
+ async subscribeAsync() {
5182
+ throw simulationUnavailableError();
5183
+ }
5184
+ };
5185
+ }
5889
5186
  var MockHost = class {
5890
5187
  constructor(venusApi) {
5891
5188
  __publicField(this, "ads");
@@ -5940,7 +5237,7 @@ var MockHost = class {
5940
5237
  this.haptics = new MockHapticsApi(venusApi);
5941
5238
  this.features = new MockFeaturesApi();
5942
5239
  this.lifecycle = this._mockLifecyclesApi;
5943
- this.simulation = new MockSimulationApi();
5240
+ this.simulation = createUnavailableSimulationApi();
5944
5241
  this.rooms = createUnavailableRoomsApi();
5945
5242
  this.logging = new MockLoggingApi();
5946
5243
  this.iap = new MockIapApi();
@@ -6432,6 +5729,11 @@ var MockHost = class {
6432
5729
  }
6433
5730
  };
6434
5731
 
5732
+ // src/utils/idGenerator.ts
5733
+ function generateId() {
5734
+ return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
5735
+ }
5736
+
6435
5737
  // src/rpc/RpcClient.ts
6436
5738
  var RpcClient = class {
6437
5739
  constructor() {
@@ -6474,7 +5776,7 @@ var RpcClient = class {
6474
5776
  }
6475
5777
  async call(method, args, timeout = 5e3) {
6476
5778
  return new Promise((resolve, reject) => {
6477
- const id = this.generateId();
5779
+ const id = generateId();
6478
5780
  this.addPendingCall(id, resolve, reject);
6479
5781
  const request = {
6480
5782
  type: "rpc-request",
@@ -6511,9 +5813,6 @@ var RpcClient = class {
6511
5813
  getPendingCall(id) {
6512
5814
  return this.pendingCalls.get(id);
6513
5815
  }
6514
- generateId() {
6515
- return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
6516
- }
6517
5816
  handleRpcResponse(response) {
6518
5817
  const pending = this.getPendingCall(response.id);
6519
5818
  if (!pending) {
@@ -6576,6 +5875,16 @@ var VenusTransport = class {
6576
5875
  this.isProcessingMessage = false;
6577
5876
  return;
6578
5877
  }
5878
+ if (message.type === "H5_SIMULATION_UPDATE" /* H5_SIMULATION_UPDATE */) {
5879
+ const notification = {
5880
+ type: "rpc-notification",
5881
+ id: message.type,
5882
+ payload: message.data
5883
+ };
5884
+ this.handleNotification(notification);
5885
+ this.isProcessingMessage = false;
5886
+ return;
5887
+ }
6579
5888
  const requestId = messageData.requestId;
6580
5889
  if (!requestId) {
6581
5890
  this.logWarn("No requestId. Ignoring message...");
@@ -6742,294 +6051,361 @@ var VenusTransport = class {
6742
6051
  }
6743
6052
  };
6744
6053
 
6745
- // src/RemoteHost.ts
6746
- init_rooms();
6747
-
6748
- // src/rooms/RpcRoomsApi.ts
6749
- init_VenusRoom();
6750
- var RpcRoomsApi = class {
6054
+ // src/simulation/RpcSimulationApi.ts
6055
+ var RpcSimulationApi = class {
6751
6056
  constructor(rpcClient) {
6752
6057
  __publicField(this, "rpcClient");
6753
- __publicField(this, "subscriptions");
6754
- __publicField(this, "transportSubscription", null);
6058
+ __publicField(this, "_simulationConfig", null);
6059
+ __publicField(this, "subscriptionCallbacks", /* @__PURE__ */ new Map());
6755
6060
  this.rpcClient = rpcClient;
6756
- this.subscriptions = {
6757
- data: {},
6758
- messages: {},
6759
- gameEvents: {},
6760
- allEvents: {}
6761
- };
6061
+ this.rpcClient.onNotification(
6062
+ "H5_SIMULATION_UPDATE" /* H5_SIMULATION_UPDATE */,
6063
+ this.handleSimulationUpdate.bind(this)
6064
+ );
6762
6065
  }
6763
- /**
6764
- * Get the subscription state for external access (used by setupRoomNotifications)
6765
- */
6766
- getSubscriptions() {
6767
- return this.subscriptions;
6066
+ isEnabled() {
6067
+ return true;
6768
6068
  }
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()
6069
+ async validateSlotAssignmentAsync(containerId, slotId, itemId) {
6070
+ return this.rpcClient.call(
6071
+ "H5_SIMULATION_VALIDATE_ASSIGNMENT" /* H5_SIMULATION_VALIDATE_ASSIGNMENT */,
6072
+ {
6073
+ containerId,
6074
+ slotId,
6075
+ itemId
6076
+ }
6777
6077
  );
6778
6078
  }
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");
6079
+ async subscribeAsync(options) {
6080
+ this.ensureValidSubscribeOptions(options);
6081
+ const subscriptionId = generateId();
6082
+ this.subscriptionCallbacks.set(subscriptionId, options.onUpdate);
6083
+ try {
6084
+ await this.rpcClient.call("H5_SIMULATION_SUBSCRIBE" /* H5_SIMULATION_SUBSCRIBE */, {
6085
+ subscriptionId,
6086
+ entities: options.entities,
6087
+ tags: options.tags,
6088
+ activeRuns: options.activeRuns,
6089
+ roomId: options.roomId
6090
+ });
6091
+ } catch (error) {
6092
+ this.subscriptionCallbacks.delete(subscriptionId);
6093
+ throw error;
6787
6094
  }
6095
+ let unsubscribed = false;
6096
+ return () => {
6097
+ if (unsubscribed) {
6098
+ return;
6099
+ }
6100
+ unsubscribed = true;
6101
+ this.subscriptionCallbacks.delete(subscriptionId);
6102
+ void this.rpcClient.call("H5_SIMULATION_UNSUBSCRIBE" /* H5_SIMULATION_UNSUBSCRIBE */, {
6103
+ subscriptionId
6104
+ }).catch((error) => {
6105
+ console.error(
6106
+ "[Venus SDK] Failed to unsubscribe simulation listener",
6107
+ error
6108
+ );
6109
+ });
6110
+ };
6111
+ }
6112
+ executeBatchOperationsAsync(operations, validateOnly) {
6113
+ return this.rpcClient.call(
6114
+ "H5_SIMULATION_BATCH_OPERATIONS" /* H5_SIMULATION_BATCH_OPERATIONS */,
6115
+ {
6116
+ operations,
6117
+ validateOnly
6118
+ }
6119
+ );
6788
6120
  }
6789
- async createRoom(options) {
6121
+ async getAvailableItemsAsync(containerId, slotId) {
6790
6122
  const response = await this.rpcClient.call(
6791
- "H5_ROOM_CREATE" /* H5_ROOM_CREATE */,
6123
+ "H5_SIMULATION_GET_AVAILABLE_ITEMS" /* H5_SIMULATION_GET_AVAILABLE_ITEMS */,
6792
6124
  {
6793
- options
6125
+ containerId,
6126
+ slotId
6127
+ }
6128
+ );
6129
+ return response.availableItems || [];
6130
+ }
6131
+ calculatePowerPreviewAsync(containerId, slotId, candidateItemId) {
6132
+ return this.rpcClient.call(
6133
+ "H5_SIMULATION_CALCULATE_POWER_PREVIEW" /* H5_SIMULATION_CALCULATE_POWER_PREVIEW */,
6134
+ {
6135
+ containerId,
6136
+ slotId,
6137
+ candidateItemId
6138
+ }
6139
+ );
6140
+ }
6141
+ assignItemToSlotAsync(containerId, slotId, itemId) {
6142
+ return this.rpcClient.call(
6143
+ "H5_SIMULATION_ASSIGN_ITEM" /* H5_SIMULATION_ASSIGN_ITEM */,
6144
+ {
6145
+ containerId,
6146
+ slotId,
6147
+ itemId
6148
+ }
6149
+ );
6150
+ }
6151
+ removeItemFromSlotAsync(containerId, slotId) {
6152
+ return this.rpcClient.call(
6153
+ "H5_SIMULATION_REMOVE_ITEM" /* H5_SIMULATION_REMOVE_ITEM */,
6154
+ {
6155
+ containerId,
6156
+ slotId
6794
6157
  }
6795
6158
  );
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;
6802
6159
  }
6803
- async joinOrCreateRoom(options) {
6160
+ async getSlotContainersAsync() {
6804
6161
  const response = await this.rpcClient.call(
6805
- "H5_ROOM_JOIN_OR_CREATE" /* H5_ROOM_JOIN_OR_CREATE */,
6162
+ "H5_SIMULATION_GET_CONTAINERS" /* H5_SIMULATION_GET_CONTAINERS */,
6163
+ {}
6164
+ );
6165
+ return response.containers || [];
6166
+ }
6167
+ async getSlotAssignmentsAsync(containerId) {
6168
+ const response = await this.rpcClient.call(
6169
+ "H5_SIMULATION_GET_ASSIGNMENTS" /* H5_SIMULATION_GET_ASSIGNMENTS */,
6806
6170
  {
6807
- options
6171
+ containerId
6172
+ }
6173
+ );
6174
+ return Array.isArray(response) ? response : response.assignments || [];
6175
+ }
6176
+ async getStateAsync(roomId) {
6177
+ const response = await this.rpcClient.call(
6178
+ "H5_SIMULATION_GET_STATE" /* H5_SIMULATION_GET_STATE */,
6179
+ {
6180
+ roomId
6181
+ }
6182
+ );
6183
+ if (response.configuration) {
6184
+ this._simulationConfig = response.configuration;
6185
+ }
6186
+ return response;
6187
+ }
6188
+ async getConfigAsync(roomId) {
6189
+ if (this._simulationConfig) {
6190
+ return this._simulationConfig;
6191
+ }
6192
+ const config = await this.rpcClient.call(
6193
+ "H5_SIMULATION_GET_CONFIG" /* H5_SIMULATION_GET_CONFIG */,
6194
+ {
6195
+ roomId
6196
+ }
6197
+ );
6198
+ if (config) {
6199
+ this._simulationConfig = config;
6200
+ return config;
6201
+ }
6202
+ throw new Error("No simulation configuration available");
6203
+ }
6204
+ executeRecipeAsync(recipeId, inputs, options) {
6205
+ return this.rpcClient.call(
6206
+ "H5_SIMULATION_EXECUTE_RECIPE" /* H5_SIMULATION_EXECUTE_RECIPE */,
6207
+ {
6208
+ recipeId,
6209
+ inputs,
6210
+ roomId: options?.roomId,
6211
+ batchAmount: options?.batchAmount,
6212
+ allowPartialBatch: options?.allowPartialBatch,
6213
+ entity: options?.entity
6808
6214
  }
6809
6215
  );
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
- };
6820
6216
  }
6821
- async joinRoomByCode(roomCode) {
6822
- const response = await this.rpcClient.call(
6823
- "H5_ROOM_JOIN_BY_CODE" /* H5_ROOM_JOIN_BY_CODE */,
6217
+ collectRecipeAsync(runId) {
6218
+ return this.rpcClient.call("H5_SIMULATION_COLLECT_RECIPE" /* H5_SIMULATION_COLLECT_RECIPE */, {
6219
+ runId
6220
+ });
6221
+ }
6222
+ getActiveRunsAsync(options) {
6223
+ return this.rpcClient.call(
6224
+ "H5_SIMULATION_GET_ACTIVE_RUNS" /* H5_SIMULATION_GET_ACTIVE_RUNS */,
6824
6225
  {
6825
- roomCode
6226
+ roomId: options?.roomId
6826
6227
  }
6827
6228
  );
6828
- if (response?.success === false) {
6829
- throw new Error(response.error || "Failed to join room by code");
6830
- }
6831
- const roomData = response.roomData || response;
6832
- const room = new VenusRoom(roomData);
6833
- return room;
6834
6229
  }
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 */,
6230
+ executeScopedRecipeAsync(recipeId, entity, inputs, options) {
6231
+ return this.rpcClient.call(
6232
+ "H5_SIMULATION_EXECUTE_SCOPED_RECIPE" /* H5_SIMULATION_EXECUTE_SCOPED_RECIPE */,
6839
6233
  {
6840
- includeArchived
6234
+ recipeId,
6235
+ entity,
6236
+ inputs,
6237
+ roomId: options?.roomId ?? null,
6238
+ options
6841
6239
  }
6842
6240
  );
6843
- if (response?.success === false) {
6844
- throw new Error(response.error || "Failed to get user rooms");
6845
- }
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;
6852
- }
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;
6865
6241
  }
6866
- async updateData(room, updates, merge = true) {
6867
- const response = await this.rpcClient.call(
6868
- "H5_ROOM_UPDATE_DATA" /* H5_ROOM_UPDATE_DATA */,
6242
+ getAvailableRecipesAsync(options) {
6243
+ return this.rpcClient.call(
6244
+ "H5_SIMULATION_GET_AVAILABLE_RECIPES" /* H5_SIMULATION_GET_AVAILABLE_RECIPES */,
6869
6245
  {
6870
- roomId: room.id,
6871
- updates,
6872
- merge
6246
+ roomId: options?.roomId || null,
6247
+ includeActorRecipes: options?.includeActorRecipes || false
6873
6248
  }
6874
6249
  );
6875
- if (response?.success === false) {
6876
- throw new Error(response.error || "Failed to update room data");
6877
- }
6878
- return response.data;
6879
6250
  }
6880
- async getData(room) {
6881
- const response = await this.rpcClient.call(
6882
- "H5_ROOM_GET_DATA" /* H5_ROOM_GET_DATA */,
6251
+ getRecipeRequirementsAsync(recipe) {
6252
+ return this.rpcClient.call(
6253
+ "H5_SIMULATION_GET_RECIPE_REQUIREMENTS" /* H5_SIMULATION_GET_RECIPE_REQUIREMENTS */,
6883
6254
  {
6884
- roomId: room.id
6255
+ recipeId: recipe.recipeId,
6256
+ entity: recipe.entity,
6257
+ batchAmount: recipe.batchAmount
6885
6258
  }
6886
6259
  );
6887
- if (response?.success === false) {
6888
- throw new Error(response.error || "Failed to get room data");
6889
- }
6890
- return response.data;
6891
6260
  }
6892
- async sendMessage(venusRoom, messageData) {
6893
- const response = await this.rpcClient.call(
6894
- "H5_ROOM_SEND_MESSAGE" /* H5_ROOM_SEND_MESSAGE */,
6261
+ getBatchRecipeRequirementsAsync(recipes) {
6262
+ return this.rpcClient.call(
6263
+ "H5_SIMULATION_GET_BATCH_RECIPE_REQUIREMENTS" /* H5_SIMULATION_GET_BATCH_RECIPE_REQUIREMENTS */,
6895
6264
  {
6896
- roomId: venusRoom.id,
6897
- message: messageData
6265
+ recipes
6898
6266
  }
6899
6267
  );
6900
- if (response?.success === false) {
6901
- throw new Error(response.error || "Failed to send message");
6902
- }
6903
- return response.messageId;
6904
6268
  }
6905
- async leave(room) {
6906
- const response = await this.rpcClient.call(
6907
- "H5_ROOM_LEAVE" /* H5_ROOM_LEAVE */,
6269
+ triggerRecipeChainAsync(recipeId, options) {
6270
+ return this.rpcClient.call(
6271
+ "H5_SIMULATION_TRIGGER_RECIPE_CHAIN" /* H5_SIMULATION_TRIGGER_RECIPE_CHAIN */,
6908
6272
  {
6909
- roomId: room.id
6273
+ triggerRecipeId: recipeId,
6274
+ context: options?.context,
6275
+ roomId: options?.roomId
6910
6276
  }
6911
6277
  );
6912
- if (response?.success === false) {
6913
- throw new Error(response.error || "Failed to leave room");
6914
- }
6915
- return response;
6916
6278
  }
6917
- async startGame(room, gameConfig = {}, turnOrder = null) {
6918
- const response = await this.rpcClient.call(
6919
- "H5_ROOM_START_GAME" /* H5_ROOM_START_GAME */,
6279
+ getEntityMetadataAsync(entityId) {
6280
+ return this.rpcClient.call(
6281
+ "H5_SIMULATION_GET_ENTITY_METADATA" /* H5_SIMULATION_GET_ENTITY_METADATA */,
6920
6282
  {
6921
- roomId: room.id,
6922
- gameConfig,
6923
- turnOrder
6283
+ entityId
6924
6284
  }
6925
6285
  );
6926
- if (response?.success === false) {
6927
- throw new Error(response.error || "Failed to start game");
6928
- }
6929
- return response.data;
6930
6286
  }
6931
- async proposeMove(room, proposalPayload) {
6287
+ async resolveFieldValueAsync(entityId, fieldPath, entity) {
6932
6288
  const response = await this.rpcClient.call(
6933
- "h5:room:proposeMove" /* H5_ROOM_PROPOSE_MOVE */,
6289
+ "H5_SIMULATION_RESOLVE_VALUE" /* H5_SIMULATION_RESOLVE_VALUE */,
6934
6290
  {
6935
- roomId: room.id,
6936
- gameSpecificState: proposalPayload.gameSpecificState,
6937
- moveType: proposalPayload.moveType,
6938
- clientContext: proposalPayload.clientContext,
6939
- clientProposalId: proposalPayload.clientProposalId
6291
+ entityId,
6292
+ fieldPath,
6293
+ entity
6940
6294
  }
6941
6295
  );
6942
- if (response?.success === false) {
6943
- throw new Error(response.error || "Failed to propose move");
6944
- }
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 };
6296
+ return response.value;
6950
6297
  }
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] = [];
6298
+ handleSimulationUpdate(notification) {
6299
+ if (!notification || !notification.subscriptionId) {
6300
+ console.warn("[Venus SDK] Received malformed simulation update");
6301
+ return;
6955
6302
  }
6956
- this.subscriptions.gameEvents[room.id].push(callback);
6957
- }
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
- });
6303
+ const callback = this.subscriptionCallbacks.get(notification.subscriptionId);
6304
+ if (!callback) {
6305
+ console.warn(
6306
+ "[Venus SDK] Received update for unknown subscription:",
6307
+ notification.subscriptionId
6308
+ );
6309
+ return;
6972
6310
  }
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
- });
6311
+ try {
6312
+ callback(notification.updates);
6313
+ } catch (error) {
6314
+ console.error("[Venus SDK] Error in simulation subscription callback", error);
6984
6315
  }
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
- }
6316
+ }
6317
+ ensureValidSubscribeOptions(options) {
6318
+ if (typeof options !== "object" || options === null) {
6319
+ throw new Error("Simulation subscribe requires an options object");
6999
6320
  }
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
- });
6321
+ const opts = options;
6322
+ if (typeof opts.onUpdate !== "function") {
6323
+ throw new Error("Simulation subscribe requires an onUpdate callback");
6324
+ }
6325
+ const hasFilter = Array.isArray(opts.entities) && opts.entities.length > 0 || Array.isArray(opts.tags) && opts.tags.length > 0 || Boolean(opts.activeRuns);
6326
+ if (!hasFilter) {
6327
+ throw new Error(
6328
+ "Simulation subscribe requires at least one filter (entities, tags, activeRuns)"
6329
+ );
7010
6330
  }
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
- };
7030
6331
  }
7031
6332
  };
7032
6333
 
6334
+ // src/simulation/index.ts
6335
+ function initializeSimulation(venusApi, host) {
6336
+ venusApi.simulation = {
6337
+ isEnabled: () => true
6338
+ };
6339
+ venusApi.simulation.getConfigAsync = () => {
6340
+ return host.simulation.getConfigAsync();
6341
+ };
6342
+ venusApi.simulation.getStateAsync = (roomId) => {
6343
+ return host.simulation.getStateAsync(roomId);
6344
+ };
6345
+ venusApi.simulation.executeRecipeAsync = (recipeId, inputs, options) => {
6346
+ return host.simulation.executeRecipeAsync(recipeId, inputs, options);
6347
+ };
6348
+ venusApi.simulation.getActiveRunsAsync = () => {
6349
+ return host.simulation.getActiveRunsAsync();
6350
+ };
6351
+ venusApi.simulation.collectRecipeAsync = (runId) => {
6352
+ return host.simulation.collectRecipeAsync(runId);
6353
+ };
6354
+ venusApi.simulation.executeScopedRecipeAsync = (recipeId, entity, inputs, options) => {
6355
+ return host.simulation.executeScopedRecipeAsync(recipeId, entity, inputs, options);
6356
+ };
6357
+ venusApi.simulation.triggerRecipeChainAsync = (recipeId, options) => {
6358
+ return host.simulation.triggerRecipeChainAsync(recipeId, options);
6359
+ };
6360
+ venusApi.simulation.getAvailableRecipesAsync = async (options) => {
6361
+ return host.simulation.getAvailableRecipesAsync(options);
6362
+ };
6363
+ venusApi.simulation.getRecipeRequirementsAsync = (recipe) => {
6364
+ return host.simulation.getRecipeRequirementsAsync(recipe);
6365
+ };
6366
+ venusApi.simulation.getBatchRecipeRequirementsAsync = (recipes) => {
6367
+ return host.simulation.getBatchRecipeRequirementsAsync(recipes);
6368
+ };
6369
+ venusApi.simulation.resolveFieldValueAsync = (entityId, fieldPath, entity) => {
6370
+ return host.simulation.resolveFieldValueAsync(entityId, fieldPath, entity);
6371
+ };
6372
+ venusApi.simulation.getEntityMetadataAsync = (entityId) => {
6373
+ return host.simulation.getEntityMetadataAsync(entityId);
6374
+ };
6375
+ venusApi.simulation.getSlotAssignmentsAsync = (containerId) => {
6376
+ return host.simulation.getSlotAssignmentsAsync(containerId);
6377
+ };
6378
+ venusApi.simulation.getSlotContainersAsync = () => {
6379
+ return host.simulation.getSlotContainersAsync();
6380
+ };
6381
+ venusApi.simulation.assignItemToSlotAsync = (containerId, slotId, itemId) => {
6382
+ return host.simulation.assignItemToSlotAsync(containerId, slotId, itemId);
6383
+ };
6384
+ venusApi.simulation.removeItemFromSlotAsync = (containerId, slotId) => {
6385
+ return host.simulation.removeItemFromSlotAsync(containerId, slotId);
6386
+ };
6387
+ venusApi.simulation.getAvailableItemsAsync = (containerId, slotId) => {
6388
+ return host.simulation.getAvailableItemsAsync(containerId, slotId);
6389
+ };
6390
+ venusApi.simulation.calculatePowerPreviewAsync = (containerId, slotId, candidateItemId) => {
6391
+ return host.simulation.calculatePowerPreviewAsync(
6392
+ containerId,
6393
+ slotId,
6394
+ candidateItemId
6395
+ );
6396
+ };
6397
+ venusApi.simulation.executeBatchOperationsAsync = (operations, validateOnly) => {
6398
+ return host.simulation.executeBatchOperationsAsync(operations, validateOnly);
6399
+ };
6400
+ venusApi.simulation.validateSlotAssignmentAsync = (containerId, slotId, itemId) => {
6401
+ return host.simulation.validateSlotAssignmentAsync(
6402
+ containerId,
6403
+ slotId,
6404
+ itemId
6405
+ );
6406
+ };
6407
+ }
6408
+
7033
6409
  // src/social/RpcSocialApi.ts
7034
6410
  var RpcSocialApi = class {
7035
6411
  constructor(rpcClient) {
@@ -7134,7 +6510,7 @@ var RemoteHost = class {
7134
6510
  this.popups = new RpcPopupsApi(rpcClient);
7135
6511
  this.profile = new HostProfileApi();
7136
6512
  this.cdn = new HostCdnApi(getCdnBaseUrl());
7137
- this.time = new HostTimeApi(rpcClient);
6513
+ this.time = new HostTimeApi(rpcClient, venusApi);
7138
6514
  this.post = new RpcPostApi(rpcClient);
7139
6515
  this.ai = new RpcAiApi(rpcClient);
7140
6516
  this.haptics = new RpcHapticsApi(rpcClient);
@@ -7150,7 +6526,6 @@ var RemoteHost = class {
7150
6526
  venusApi.isMock = () => false;
7151
6527
  this.venusApi.sharedAssets = new RpcSharedAssetsApi(rpcClient, venusApi);
7152
6528
  initializeRoomsApi(this.venusApi, this);
7153
- console.log("[Venus SDK] Remote host created");
7154
6529
  }
7155
6530
  get isInitialized() {
7156
6531
  return this._isInitialized;
@@ -7209,19 +6584,14 @@ var RemoteHost = class {
7209
6584
  // src/Host.ts
7210
6585
  function createHost(venusApi, isMock) {
7211
6586
  if (isMock) {
7212
- console.log("[Venus SDK] Creating Local Host");
7213
6587
  return new MockHost(venusApi);
7214
6588
  } else {
7215
- console.log("[Venus SDK] Creating Remote Host");
7216
6589
  return new RemoteHost(venusApi);
7217
6590
  }
7218
6591
  }
7219
6592
 
7220
- // src/venus-api/index.js
7221
- init_rooms();
7222
-
7223
6593
  // src/version.ts
7224
- var SDK_VERSION = "3.0.4";
6594
+ var SDK_VERSION = "3.0.5";
7225
6595
 
7226
6596
  // src/social/index.ts
7227
6597
  function initializeSocial(venusApi, host) {
@@ -7282,67 +6652,6 @@ var VenusAPI2 = class {
7282
6652
  height: 60
7283
6653
  }
7284
6654
  },
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
6655
  // Static locale data at top level
7347
6656
  locale: "en-US",
7348
6657
  languageCode: "en",
@@ -7473,58 +6782,26 @@ var VenusAPI2 = class {
7473
6782
  deviceType: "phone",
7474
6783
  hapticsEnabled: false,
7475
6784
  haptics: { supported: false, enabled: false }
6785
+ }
6786
+ });
6787
+ const originalConfig = this.config;
6788
+ this.config = new Proxy(originalConfig, {
6789
+ get(target, prop) {
6790
+ if (prop === "locale" || prop === "languageCode") {
6791
+ console.error(
6792
+ `[Venus SDK] config.${prop} is deprecated and will be removed in v4.0.0. Use VenusAPI.${prop === "locale" ? "getLocale()" : "getLanguageCode()"}() instead.`
6793
+ );
6794
+ }
6795
+ return target[prop];
7476
6796
  },
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
- }
6797
+ set(target, prop, value) {
6798
+ if (prop === "locale" || prop === "languageCode") {
6799
+ console.error(
6800
+ `[Venus SDK] config.${prop} is deprecated and will be removed in v4.0.0. Use VenusAPI.${prop === "locale" ? "getLocale()" : "getLanguageCode()"}() instead.`
6801
+ );
7527
6802
  }
6803
+ target[prop] = value;
6804
+ return true;
7528
6805
  }
7529
6806
  });
7530
6807
  const isInsideHostedEnv = this._bootstrap.isInsideHostedEnvironment;
@@ -7533,7 +6810,6 @@ var VenusAPI2 = class {
7533
6810
  initializeStorage(this, host);
7534
6811
  initializeRoomsApi(this, host);
7535
6812
  initializeAds(this, host);
7536
- initializeTheme(this);
7537
6813
  initializePopups(this, host);
7538
6814
  initializeAnalytics(this, host);
7539
6815
  initializeIap(this, host);
@@ -7557,6 +6833,28 @@ var VenusAPI2 = class {
7557
6833
  initializeSimulation(this, host);
7558
6834
  initializeSocial(this, host);
7559
6835
  initializeAssetLoader(this, createProxiedMethod);
6836
+ this.getLocale = () => {
6837
+ if (typeof window !== "undefined" && window.venus) {
6838
+ const venus = window.venus;
6839
+ if (venus.config && venus.config.locale) {
6840
+ return venus.config.locale;
6841
+ }
6842
+ if (venus._config && venus._config.locale) {
6843
+ return venus._config.locale;
6844
+ }
6845
+ if (venus.config?.environment?.browserInfo?.language) {
6846
+ return venus.config.environment.browserInfo.language;
6847
+ }
6848
+ }
6849
+ if (typeof navigator !== "undefined" && navigator.language) {
6850
+ return navigator.language;
6851
+ }
6852
+ return "en-US";
6853
+ };
6854
+ this.getLanguageCode = () => {
6855
+ const locale = this.getLocale();
6856
+ return locale.split("-")[0];
6857
+ };
7560
6858
  }
7561
6859
  // Generate deterministic instance ID based on current page URL
7562
6860
  _generateDeterministicInstanceId() {
@@ -7593,13 +6891,9 @@ var VenusAPI2 = class {
7593
6891
  // BOOTSTRAP METHODS
7594
6892
  //---------------------------------------
7595
6893
  _detectHostedEnvironment() {
7596
- console.log("[Venus SDK] Detecting host environment...");
7597
6894
  const isInIframe = window.self !== window.top;
7598
6895
  const hasReactNativeWebView = typeof window.ReactNativeWebView !== "undefined";
7599
6896
  this._bootstrap.isInsideHostedEnvironment = isInIframe || hasReactNativeWebView;
7600
- console.log(
7601
- `[Venus SDK] isInIframe: ${isInIframe}, hasReactNativeWebView: ${hasReactNativeWebView}`
7602
- );
7603
6897
  }
7604
6898
  isMobile() {
7605
6899
  return typeof window.ReactNativeWebView !== "undefined";
@@ -7654,7 +6948,6 @@ instance.isAvailable = function() {
7654
6948
  (async () => {
7655
6949
  try {
7656
6950
  await initializeNumbers(instance);
7657
- console.log("[Venus SDK] Numbers system initialized");
7658
6951
  } catch (error) {
7659
6952
  console.error("[Venus SDK] Failed to initialize numbers system:", error);
7660
6953
  }