@series-inc/venus-sdk 3.1.2 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/{AdsApi-CNGRf6j0.d.mts → AdsApi-DFutZ7_q.d.mts} +501 -293
  2. package/dist/{AdsApi-CNGRf6j0.d.ts → AdsApi-DFutZ7_q.d.ts} +501 -293
  3. package/dist/{chunk-PXWCNWJ6.mjs → chunk-AGXMORDL.mjs} +1442 -1586
  4. package/dist/chunk-AGXMORDL.mjs.map +1 -0
  5. package/dist/chunk-NSSMTXJJ.mjs +7 -0
  6. package/dist/chunk-NSSMTXJJ.mjs.map +1 -0
  7. package/dist/{chunk-W7IPHM67.mjs → chunk-QABXMFND.mjs} +3 -26
  8. package/dist/chunk-QABXMFND.mjs.map +1 -0
  9. package/dist/chunk-UXY5CKKG.mjs +12 -0
  10. package/dist/chunk-UXY5CKKG.mjs.map +1 -0
  11. package/dist/core-62LWDHN7.mjs +4 -0
  12. package/dist/{core-R3FHW62G.mjs.map → core-62LWDHN7.mjs.map} +1 -1
  13. package/dist/index.cjs +1461 -1585
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.d.mts +280 -92
  16. package/dist/index.d.ts +280 -92
  17. package/dist/index.mjs +4 -6
  18. package/dist/index.mjs.map +1 -1
  19. package/dist/venus-api/index.cjs +1557 -2020
  20. package/dist/venus-api/index.cjs.map +1 -1
  21. package/dist/venus-api/index.d.mts +2 -2
  22. package/dist/venus-api/index.d.ts +2 -2
  23. package/dist/venus-api/index.mjs +92 -391
  24. package/dist/venus-api/index.mjs.map +1 -1
  25. package/dist/vite/index.cjs +534 -0
  26. package/dist/vite/index.cjs.map +1 -0
  27. package/dist/vite/index.mjs +527 -0
  28. package/dist/vite/index.mjs.map +1 -0
  29. package/dist/webview/index.cjs +15 -0
  30. package/dist/webview/index.cjs.map +1 -0
  31. package/dist/webview/index.d.mts +15 -0
  32. package/dist/webview/index.d.ts +15 -0
  33. package/dist/webview/index.mjs +4 -0
  34. package/dist/webview/index.mjs.map +1 -0
  35. package/package.json +1 -1
  36. package/dist/chunk-PXWCNWJ6.mjs.map +0 -1
  37. package/dist/chunk-W7IPHM67.mjs.map +0 -1
  38. package/dist/core-R3FHW62G.mjs +0 -3
@@ -1,219 +1,5 @@
1
- import { __esm, __export, __publicField, createMockDelay, MOCK_DELAYS, isWebPlatform, __toCommonJS } from './chunk-W7IPHM67.mjs';
2
-
3
- // src/rooms/VenusRoom.ts
4
- var VenusRoom;
5
- var init_VenusRoom = __esm({
6
- "src/rooms/VenusRoom.ts"() {
7
- VenusRoom = class {
8
- constructor(roomData) {
9
- __publicField(this, "id");
10
- __publicField(this, "name");
11
- __publicField(this, "players");
12
- __publicField(this, "maxPlayers");
13
- __publicField(this, "gameType");
14
- __publicField(this, "appId");
15
- __publicField(this, "type");
16
- __publicField(this, "createdBy");
17
- __publicField(this, "createdAt");
18
- __publicField(this, "updatedAt");
19
- __publicField(this, "isPrivate");
20
- __publicField(this, "currentPlayers");
21
- __publicField(this, "status");
22
- __publicField(this, "customMetadata");
23
- __publicField(this, "admins");
24
- __publicField(this, "roomCode");
25
- __publicField(this, "description");
26
- __publicField(this, "data");
27
- __publicField(this, "version");
28
- __publicField(this, "_subscriptions", /* @__PURE__ */ new Map());
29
- this.id = roomData.id;
30
- this.name = roomData.name;
31
- this.players = roomData.currentPlayers || [];
32
- this.maxPlayers = roomData.maxPlayers;
33
- this.gameType = roomData.gameType;
34
- this.appId = roomData.appId;
35
- this.type = roomData.type;
36
- this.createdBy = roomData.createdBy;
37
- this.createdAt = roomData.createdAt;
38
- this.updatedAt = roomData.updatedAt;
39
- this.isPrivate = roomData.isPrivate;
40
- this.currentPlayers = roomData.currentPlayers || [];
41
- this.status = roomData.status;
42
- this.customMetadata = roomData.customMetadata || {};
43
- this.admins = roomData.admins || [];
44
- this.roomCode = roomData.roomCode;
45
- this.description = roomData.description;
46
- this.data = roomData.data || {};
47
- this.version = roomData.version;
48
- console.log(`VenusRoom: Created room object for ${this.id}`, {
49
- hasCustomMetadata: !!this.customMetadata,
50
- hasGameState: !!this.customMetadata?.rules?.gameState,
51
- gamePhase: this.customMetadata?.rules?.gameState?.phase,
52
- currentPlayer: this.customMetadata?.rules?.gameState?.currentPlayer
53
- });
54
- }
55
- updateFromRoomData(newRoomData) {
56
- if (newRoomData.id === this.id) {
57
- this.name = newRoomData.name || this.name;
58
- this.players = newRoomData.currentPlayers || this.players;
59
- this.maxPlayers = newRoomData.maxPlayers || this.maxPlayers;
60
- this.gameType = newRoomData.gameType || this.gameType;
61
- this.currentPlayers = newRoomData.currentPlayers || this.currentPlayers;
62
- this.customMetadata = newRoomData.customMetadata || this.customMetadata;
63
- this.data = newRoomData.data || this.data;
64
- this.status = newRoomData.status || this.status;
65
- this.updatedAt = newRoomData.updatedAt || this.updatedAt;
66
- console.log(`VenusRoom: Updated room object ${this.id} with fresh data`, {
67
- hasCustomMetadata: !!this.customMetadata,
68
- hasGameState: !!this.customMetadata?.rules?.gameState,
69
- gamePhase: this.customMetadata?.rules?.gameState?.phase,
70
- currentPlayer: this.customMetadata?.rules?.gameState?.currentPlayer
71
- });
72
- }
73
- }
74
- };
75
- }
76
- });
77
-
78
- // src/rooms/RoomsApi.ts
79
- var init_RoomsApi = __esm({
80
- "src/rooms/RoomsApi.ts"() {
81
- }
82
- });
83
-
84
- // src/rooms/index.ts
85
- var rooms_exports = {};
86
- __export(rooms_exports, {
87
- VenusRoom: () => VenusRoom,
88
- initializeRoomsApi: () => initializeRoomsApi,
89
- setupRoomNotifications: () => setupRoomNotifications
90
- });
91
- function bindMethod(target, targetKey, source, sourceKey) {
92
- const key = sourceKey ?? targetKey;
93
- const fn = source?.[key];
94
- if (typeof fn === "function") {
95
- target[targetKey] = fn.bind(source);
96
- return true;
97
- }
98
- return false;
99
- }
100
- function setupRoomNotifications(transport, getSubscriptions) {
101
- console.log("[Venus Rooms] Setting up room notification listeners");
102
- return transport.onVenusMessage((message) => {
103
- const subscriptions = getSubscriptions();
104
- if (!subscriptions) {
105
- return;
106
- }
107
- if (message.type === "H5_ROOM_DATA_UPDATED") {
108
- const messageData = message.data;
109
- const { roomId, roomData } = messageData;
110
- if (!roomId) return;
111
- const callbacks = subscriptions.data?.[roomId] || [];
112
- const allEventsCallbacks = subscriptions.allEvents?.[roomId] || [];
113
- console.log(`[Venus Rooms] \u{1F514} Room data updated for ${roomId}, notifying ${callbacks.length} callbacks`, roomData);
114
- callbacks.forEach((callback) => {
115
- try {
116
- callback(roomData);
117
- } catch (error) {
118
- console.error("[Venus Rooms] Error in room data callback:", error);
119
- throw error;
120
- }
121
- });
122
- allEventsCallbacks.forEach((callback) => {
123
- try {
124
- callback({ type: message.type, ...messageData });
125
- } catch (error) {
126
- console.error("[Venus Rooms] Error in allEvents callback:", error);
127
- throw error;
128
- }
129
- });
130
- }
131
- if (message.type === "H5_ROOM_MESSAGE_RECEIVED" || message.type === "H5_ROOM_MESSAGE_UPDATED" || message.type === "H5_ROOM_MESSAGE_DELETED") {
132
- const messageData = message.data;
133
- const { roomId } = messageData;
134
- if (!roomId) return;
135
- const callbacks = subscriptions.messages?.[roomId] || [];
136
- const allEventsCallbacks = subscriptions.allEvents?.[roomId] || [];
137
- console.log(`[Venus Rooms] \u{1F514} Room message event for ${roomId}, notifying ${callbacks.length} callbacks`);
138
- callbacks.forEach((callback) => {
139
- try {
140
- callback(messageData);
141
- } catch (error) {
142
- console.error("[Venus Rooms] Error in room message callback:", error);
143
- throw error;
144
- }
145
- });
146
- allEventsCallbacks.forEach((callback) => {
147
- try {
148
- callback({ type: message.type, ...messageData });
149
- } catch (error) {
150
- console.error("[Venus Rooms] Error in allEvents callback:", error);
151
- throw error;
152
- }
153
- });
154
- }
155
- if (message.type === "app:h5:proposedMoveValidationUpdated") {
156
- const messageData = message.data;
157
- const { roomId } = messageData;
158
- if (!roomId) return;
159
- const callbacks = subscriptions.gameEvents?.[roomId] || [];
160
- const allEventsCallbacks = subscriptions.allEvents?.[roomId] || [];
161
- console.log(`[Venus Rooms] \u{1F514} Proposed move validation updated for ${roomId}, notifying ${callbacks.length} callbacks`);
162
- callbacks.forEach((callback) => {
163
- try {
164
- callback(messageData);
165
- } catch (error) {
166
- console.error("[Venus Rooms] Error in game event callback:", error);
167
- throw error;
168
- }
169
- });
170
- allEventsCallbacks.forEach((callback) => {
171
- try {
172
- callback({ type: message.type, ...messageData });
173
- } catch (error) {
174
- console.error("[Venus Rooms] Error in allEvents callback:", error);
175
- throw error;
176
- }
177
- });
178
- }
179
- });
180
- }
181
- function initializeRoomsApi(venusApi, host) {
182
- const roomsApi = host?.rooms;
183
- if (!roomsApi) {
184
- console.warn(
185
- "[Venus SDK] Host did not provide a rooms implementation. Rooms API will be unavailable."
186
- );
187
- return;
188
- }
189
- const venus = venusApi;
190
- const existingNamespace = venus.rooms || {};
191
- const roomsNamespace = Object.assign({}, existingNamespace);
192
- const namespaceBindings = [
193
- ["create", "createRoom"],
194
- ["joinOrCreate", "joinOrCreateRoom"],
195
- ["joinByCode", "joinRoomByCode"],
196
- ["list", "getUserRooms"],
197
- ["subscribeToRoom", "subscribe"],
198
- ["updateRoomData", "updateData"],
199
- ["getRoomData", "getData"],
200
- ["sendRoomMessage", "sendMessage"],
201
- ["leaveRoom", "leave"],
202
- ["startRoomGame", "startGame"],
203
- ["proposeMove"],
204
- ["validateMove"]
205
- ];
206
- namespaceBindings.forEach(([targetKey, sourceKey]) => {
207
- bindMethod(roomsNamespace, targetKey, roomsApi, sourceKey);
208
- });
209
- venus.rooms = roomsNamespace;
210
- }
211
- var init_rooms = __esm({
212
- "src/rooms/index.ts"() {
213
- init_RoomsApi();
214
- init_VenusRoom();
215
- }
216
- });
1
+ import { createMockDelay, MOCK_DELAYS, isWebPlatform } from './chunk-QABXMFND.mjs';
2
+ import { __publicField } from './chunk-NSSMTXJJ.mjs';
217
3
 
218
4
  // src/VenusMessageId.ts
219
5
  var VenusMessageId = /* @__PURE__ */ ((VenusMessageId2) => {
@@ -261,10 +47,6 @@ var VenusMessageId = /* @__PURE__ */ ((VenusMessageId2) => {
261
47
  VenusMessageId2["CONFIRM_DIALOG"] = "H5_CONFIRM_DIALOG";
262
48
  VenusMessageId2["ACTION_SHEET_SHOW"] = "H5_ACTION_SHEET_SHOW";
263
49
  VenusMessageId2["REQUEST_SERVER_TIME"] = "H5_REQUEST_SERVER_TIME";
264
- VenusMessageId2["GET_POST_INTERACTIONS"] = "H5_GET_POST_INTERACTIONS";
265
- VenusMessageId2["TOGGLE_LIKE"] = "H5_TOGGLE_LIKE";
266
- VenusMessageId2["OPEN_COMMENTS"] = "H5_OPEN_COMMENTS";
267
- VenusMessageId2["TOGGLE_FOLLOW"] = "H5_TOGGLE_FOLLOW";
268
50
  VenusMessageId2["SHARE_LINK"] = "H5_SHARE_LINK";
269
51
  VenusMessageId2["CREATE_SHARE_QRCODE"] = "H5_CREATE_SHARE_QRCODE";
270
52
  VenusMessageId2["AI_CHAT_COMPLETION"] = "H5_AI_CHAT_COMPLETION";
@@ -306,11 +88,14 @@ var VenusMessageId = /* @__PURE__ */ ((VenusMessageId2) => {
306
88
  VenusMessageId2["H5_SIMULATION_GET_AVAILABLE_ITEMS"] = "H5_SIMULATION_GET_AVAILABLE_ITEMS";
307
89
  VenusMessageId2["H5_SIMULATION_VALIDATE_ASSIGNMENT"] = "H5_SIMULATION_VALIDATE_ASSIGNMENT";
308
90
  VenusMessageId2["H5_SIMULATION_BATCH_OPERATIONS"] = "H5_SIMULATION_BATCH_OPERATIONS";
309
- VenusMessageId2["H5_LEADERBOARD_START_RUN"] = "H5_LEADERBOARD_START_RUN";
91
+ VenusMessageId2["H5_SIMULATION_SUBSCRIBE"] = "H5_SIMULATION_SUBSCRIBE";
92
+ VenusMessageId2["H5_SIMULATION_UNSUBSCRIBE"] = "H5_SIMULATION_UNSUBSCRIBE";
93
+ VenusMessageId2["H5_SIMULATION_UPDATE"] = "H5_SIMULATION_UPDATE";
94
+ VenusMessageId2["H5_LEADERBOARD_CREATE_SCORE_TOKEN"] = "H5_LEADERBOARD_CREATE_SCORE_TOKEN";
310
95
  VenusMessageId2["H5_LEADERBOARD_SUBMIT_SCORE"] = "H5_LEADERBOARD_SUBMIT_SCORE";
311
- VenusMessageId2["H5_LEADERBOARD_GET"] = "H5_LEADERBOARD_GET";
312
- VenusMessageId2["H5_LEADERBOARD_GET_HIGHLIGHT"] = "H5_LEADERBOARD_GET_HIGHLIGHT";
313
- VenusMessageId2["H5_LEADERBOARD_GET_PLAYER_STATS"] = "H5_LEADERBOARD_GET_PLAYER_STATS";
96
+ VenusMessageId2["H5_LEADERBOARD_GET_PAGED_SCORES"] = "H5_LEADERBOARD_GET_PAGED_SCORES";
97
+ VenusMessageId2["H5_LEADERBOARD_GET_PODIUM_SCORES"] = "H5_LEADERBOARD_GET_PODIUM_SCORES";
98
+ VenusMessageId2["H5_LEADERBOARD_GET_MY_RANK"] = "H5_LEADERBOARD_GET_MY_RANK";
314
99
  VenusMessageId2["H5_ROOM_CREATE"] = "H5_ROOM_CREATE";
315
100
  VenusMessageId2["H5_ROOM_JOIN"] = "H5_ROOM_JOIN";
316
101
  VenusMessageId2["H5_ROOM_JOIN_OR_CREATE"] = "H5_ROOM_JOIN_OR_CREATE";
@@ -553,7 +338,7 @@ var MockAvatarApi = class {
553
338
  async deleteAvatar() {
554
339
  console.log(`[Venus Mock] Deleting avatar3d config`);
555
340
  const venusApi = this._venusApi;
556
- const currentProfile = venusApi.getCurrentProfile();
341
+ const currentProfile = venusApi.getProfile();
557
342
  const profileId = currentProfile?.id || "default_profile";
558
343
  localStorage.removeItem(`venus-mock-avatar3d-${profileId}`);
559
344
  console.log(
@@ -568,7 +353,7 @@ var MockAvatarApi = class {
568
353
  console.log(`[Venus Mock] Loading shared avatar3d by ID: ${avatar3dId}`);
569
354
  config = await this.selectAvatarConfig(avatar3dId, false);
570
355
  } else {
571
- const currentProfile = venusApi.getCurrentProfile();
356
+ const currentProfile = venusApi.getProfile();
572
357
  const profileId = currentProfile?.id || "default_profile";
573
358
  console.log(`[Venus Mock] Loading avatar3d for profile: ${profileId}`);
574
359
  console.log(
@@ -585,7 +370,7 @@ var MockAvatarApi = class {
585
370
  async saveAvatar(config) {
586
371
  console.log(`[Venus Mock] Saving avatar3d config:`, config);
587
372
  const venusApi = this._venusApi;
588
- const currentProfile = venusApi.getCurrentProfile();
373
+ const currentProfile = venusApi.getProfile();
589
374
  const profileId = currentProfile?.id || "default_profile";
590
375
  localStorage.setItem(
591
376
  `venus-mock-avatar3d-${profileId}`,
@@ -1101,7 +886,8 @@ var HostCdnApi = class {
1101
886
  return index === pathParts.length - 1 ? encodeURIComponent(part) : part;
1102
887
  });
1103
888
  const encodedSubPath = encodedParts.join("/");
1104
- const fullUrl = this.baseUrl + "/" + encodedSubPath;
889
+ const cacheBust = Date.now();
890
+ const fullUrl = this.baseUrl + "/" + encodedSubPath + `?cacheBust=${cacheBust}`;
1105
891
  return fullUrl;
1106
892
  }
1107
893
  resolveAvatarAssetUrl(subPath) {
@@ -1116,9 +902,15 @@ var HostCdnApi = class {
1116
902
 
1117
903
  // src/cdn/MockCdnApi.ts
1118
904
  var MockCdnApi = class {
1119
- constructor() {
1120
- __publicField(this, "baseUrl");
1121
- this.baseUrl = "https://venus-static-01293ak.web.app/";
905
+ constructor(venusApi) {
906
+ __publicField(this, "venusApi");
907
+ this.venusApi = venusApi;
908
+ }
909
+ get baseUrl() {
910
+ return this.venusApi._mock?.cdnBaseUrl ?? "https://venus-static-01293ak.web.app/";
911
+ }
912
+ get forceRemoteCdn() {
913
+ return this.venusApi._mock?.cdnForceRemote ?? false;
1122
914
  }
1123
915
  async fetchBlob(path, options) {
1124
916
  const controller = new AbortController();
@@ -1155,6 +947,10 @@ var MockCdnApi = class {
1155
947
  return subPath;
1156
948
  }
1157
949
  const cleanSubPath = subPath.startsWith("/") ? subPath.slice(1) : subPath;
950
+ const isLocalhost = typeof window !== "undefined" && (window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1");
951
+ if (isLocalhost && !this.forceRemoteCdn) {
952
+ return `/${cleanSubPath}`;
953
+ }
1158
954
  const pathParts = cleanSubPath.split("/");
1159
955
  const encodedParts = pathParts.map((part, index) => {
1160
956
  return index === pathParts.length - 1 ? encodeURIComponent(part) : part;
@@ -1276,6 +1072,212 @@ function initializeCdn(venusApi, host) {
1276
1072
  venusApi.cdn = host.cdn;
1277
1073
  }
1278
1074
 
1075
+ // src/device/HostDeviceApi.ts
1076
+ var HostDeviceApi = class {
1077
+ constructor(venusApi) {
1078
+ __publicField(this, "venusApi");
1079
+ this.venusApi = venusApi;
1080
+ }
1081
+ getDevice() {
1082
+ const device = this.venusApi._deviceData;
1083
+ if (!device) {
1084
+ throw new Error(
1085
+ "[Venus SDK] Device info not available. You must await VenusAPI.initializeAsync() before calling getDevice(). INIT_SDK has not completed."
1086
+ );
1087
+ }
1088
+ return device;
1089
+ }
1090
+ };
1091
+
1092
+ // src/device/MockDeviceApi.ts
1093
+ var MockDeviceApi = class {
1094
+ constructor(venusApi) {
1095
+ __publicField(this, "venusApi");
1096
+ this.venusApi = venusApi;
1097
+ }
1098
+ getDevice() {
1099
+ const width = typeof window !== "undefined" ? window.innerWidth : 400;
1100
+ const height = typeof window !== "undefined" ? window.innerHeight : 800;
1101
+ return {
1102
+ screenSize: { width, height },
1103
+ viewportSize: {
1104
+ width: width - 20,
1105
+ // account for safe area
1106
+ height: height - 20
1107
+ },
1108
+ orientation: width > height ? "landscape" : "portrait",
1109
+ pixelRatio: typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1,
1110
+ fontScale: 1,
1111
+ deviceType: width > 768 ? "tablet" : "phone",
1112
+ hapticsEnabled: false,
1113
+ haptics: { supported: false, enabled: false }
1114
+ };
1115
+ }
1116
+ };
1117
+
1118
+ // src/environment/HostEnvironmentApi.ts
1119
+ var HostEnvironmentApi = class {
1120
+ constructor(venusApi) {
1121
+ __publicField(this, "venusApi");
1122
+ this.venusApi = venusApi;
1123
+ }
1124
+ getEnvironment() {
1125
+ const environment = this.venusApi._environmentData;
1126
+ if (!environment) {
1127
+ throw new Error(
1128
+ "[Venus SDK] Environment info not available. You must await VenusAPI.initializeAsync() before calling getEnvironment(). INIT_SDK has not completed."
1129
+ );
1130
+ }
1131
+ return environment;
1132
+ }
1133
+ };
1134
+
1135
+ // src/environment/MockEnvironmentApi.ts
1136
+ var MockEnvironmentApi = class {
1137
+ constructor(venusApi) {
1138
+ __publicField(this, "venusApi");
1139
+ this.venusApi = venusApi;
1140
+ }
1141
+ getEnvironment() {
1142
+ const getBrowser = () => {
1143
+ if (typeof navigator === "undefined") return "unknown";
1144
+ const userAgent = navigator.userAgent;
1145
+ if (/chrome|chromium|crios/i.test(userAgent)) return "chrome";
1146
+ if (/firefox|fxios/i.test(userAgent)) return "firefox";
1147
+ if (/safari/i.test(userAgent)) return "safari";
1148
+ if (/edg/i.test(userAgent)) return "edge";
1149
+ if (/opera|opr/i.test(userAgent)) return "opera";
1150
+ return "unknown";
1151
+ };
1152
+ return {
1153
+ isDevelopment: true,
1154
+ platform: "web",
1155
+ platformVersion: "mock-1.0",
1156
+ browserInfo: {
1157
+ browser: getBrowser(),
1158
+ userAgent: typeof navigator !== "undefined" ? navigator.userAgent : "mock-agent",
1159
+ isMobile: typeof navigator !== "undefined" ? /Mobi|Android/i.test(navigator.userAgent) : false,
1160
+ isTablet: typeof navigator !== "undefined" ? /iPad|Tablet|Pad/i.test(navigator.userAgent) : false,
1161
+ language: typeof navigator !== "undefined" ? navigator.language || "en-US" : "en-US"
1162
+ }
1163
+ };
1164
+ }
1165
+ };
1166
+
1167
+ // src/system/HostSystemApi.ts
1168
+ var HostSystemApi = class {
1169
+ constructor(deviceApi, environmentApi, venusApi) {
1170
+ __publicField(this, "deviceApi");
1171
+ __publicField(this, "environmentApi");
1172
+ __publicField(this, "venusApi");
1173
+ this.deviceApi = deviceApi;
1174
+ this.environmentApi = environmentApi;
1175
+ this.venusApi = venusApi;
1176
+ }
1177
+ getDevice() {
1178
+ return this.deviceApi.getDevice();
1179
+ }
1180
+ getEnvironment() {
1181
+ return this.environmentApi.getEnvironment();
1182
+ }
1183
+ getSafeArea() {
1184
+ const safeArea = this.venusApi._safeAreaData;
1185
+ if (!safeArea) {
1186
+ throw new Error(
1187
+ "[Venus SDK] getSafeArea() called before initialization. Call VenusAPI.initializeAsync() first."
1188
+ );
1189
+ }
1190
+ return { ...safeArea };
1191
+ }
1192
+ isMobile() {
1193
+ const environment = this.environmentApi.getEnvironment();
1194
+ if (environment.platform === "ios" || environment.platform === "android") {
1195
+ return true;
1196
+ }
1197
+ if (environment.browserInfo) {
1198
+ return environment.browserInfo.isMobile;
1199
+ }
1200
+ return true;
1201
+ }
1202
+ isWeb() {
1203
+ const environment = this.environmentApi.getEnvironment();
1204
+ if (environment.platform === "web") {
1205
+ return true;
1206
+ }
1207
+ if (environment.browserInfo && !environment.browserInfo.isMobile) {
1208
+ return true;
1209
+ }
1210
+ return false;
1211
+ }
1212
+ };
1213
+
1214
+ // src/system/MockSystemApi.ts
1215
+ var MockSystemApi = class {
1216
+ constructor(deviceApi, environmentApi, venusApi) {
1217
+ __publicField(this, "deviceApi");
1218
+ __publicField(this, "environmentApi");
1219
+ __publicField(this, "venusApi");
1220
+ this.deviceApi = deviceApi;
1221
+ this.environmentApi = environmentApi;
1222
+ this.venusApi = venusApi;
1223
+ }
1224
+ getDevice() {
1225
+ return this.deviceApi.getDevice();
1226
+ }
1227
+ getEnvironment() {
1228
+ return this.environmentApi.getEnvironment();
1229
+ }
1230
+ getSafeArea() {
1231
+ const safeArea = this.venusApi._safeAreaData;
1232
+ if (!safeArea) {
1233
+ return {
1234
+ top: 0,
1235
+ right: 0,
1236
+ bottom: 34,
1237
+ left: 0
1238
+ };
1239
+ }
1240
+ return { ...safeArea };
1241
+ }
1242
+ isMobile() {
1243
+ const environment = this.environmentApi.getEnvironment();
1244
+ if (environment.platform === "ios" || environment.platform === "android") {
1245
+ return true;
1246
+ }
1247
+ if (environment.browserInfo) {
1248
+ return environment.browserInfo.isMobile;
1249
+ }
1250
+ return true;
1251
+ }
1252
+ isWeb() {
1253
+ const environment = this.environmentApi.getEnvironment();
1254
+ if (environment.platform === "web") {
1255
+ return true;
1256
+ }
1257
+ if (environment.browserInfo && !environment.browserInfo.isMobile) {
1258
+ return true;
1259
+ }
1260
+ return false;
1261
+ }
1262
+ };
1263
+
1264
+ // src/system/index.ts
1265
+ function initializeSystem(venusApi, host) {
1266
+ venusApi.system = host.system;
1267
+ venusApi.isMobile = () => {
1268
+ console.warn(
1269
+ "[Venus SDK] DEPRECATED: VenusAPI.isMobile() is deprecated. Use VenusAPI.system.isMobile() instead."
1270
+ );
1271
+ return host.system.isMobile();
1272
+ };
1273
+ venusApi.isWeb = () => {
1274
+ console.warn(
1275
+ "[Venus SDK] DEPRECATED: VenusAPI.isWeb() is deprecated. Use VenusAPI.system.isWeb() instead."
1276
+ );
1277
+ return host.system.isWeb();
1278
+ };
1279
+ }
1280
+
1279
1281
  // src/features/RpcFeaturesApi.ts
1280
1282
  var RpcFeaturesApi = class {
1281
1283
  constructor(rcpClient) {
@@ -1758,13 +1760,8 @@ var MockNotificationsApi = class {
1758
1760
  async cancelNotification(notificationId) {
1759
1761
  const venusApi = this.venusApi;
1760
1762
  if (isWebPlatform()) {
1761
- console.log(
1762
- "[Venus Mock] Cancel notification on web platform (simulated):",
1763
- notificationId
1764
- );
1765
1763
  return true;
1766
1764
  }
1767
- console.log("[Venus Mock] Cancel local notification:", notificationId);
1768
1765
  await createMockDelay(MOCK_DELAYS.short);
1769
1766
  if (venusApi._mock.scheduledNotifications && venusApi._mock.scheduledNotifications[notificationId]) {
1770
1767
  delete venusApi._mock.scheduledNotifications[notificationId];
@@ -1774,12 +1771,8 @@ var MockNotificationsApi = class {
1774
1771
  }
1775
1772
  async getAllScheduledLocalNotifications() {
1776
1773
  if (isWebPlatform()) {
1777
- console.log(
1778
- "[Venus Mock] Get notifications on web platform (returning empty list)"
1779
- );
1780
1774
  return [];
1781
1775
  }
1782
- console.log("[Venus Mock] Get all scheduled local notifications");
1783
1776
  await createMockDelay(MOCK_DELAYS.short);
1784
1777
  const venusApi = this.venusApi;
1785
1778
  const notifications = venusApi._mock.scheduledNotifications || {};
@@ -1787,10 +1780,8 @@ var MockNotificationsApi = class {
1787
1780
  }
1788
1781
  async isLocalNotificationsEnabled() {
1789
1782
  if (isWebPlatform()) {
1790
- console.log("[Venus Mock] Notifications not available on web platform");
1791
1783
  return false;
1792
1784
  }
1793
- console.log("[Venus Mock] Check if local notifications are enabled");
1794
1785
  await createMockDelay(MOCK_DELAYS.short);
1795
1786
  const venusApi = this.venusApi;
1796
1787
  const isEnabled = venusApi._mock.notificationsEnabled !== false;
@@ -1799,9 +1790,6 @@ var MockNotificationsApi = class {
1799
1790
  async scheduleAsync(title, body, seconds, notificationId, options) {
1800
1791
  const { priority = 50, groupId, payload } = options || {};
1801
1792
  if (isWebPlatform()) {
1802
- console.log(
1803
- "[Venus Mock] Notifications not supported on web platform, simulating success"
1804
- );
1805
1793
  console.info(
1806
1794
  "\u{1F514} [Venus Mock] Notification would be scheduled:",
1807
1795
  title || "Untitled",
@@ -1812,14 +1800,11 @@ var MockNotificationsApi = class {
1812
1800
  const mockId = `mock-web-notification-${Date.now()}`;
1813
1801
  return mockId;
1814
1802
  }
1815
- console.log("[Venus Mock] Schedule local notification:", { title, body, seconds, options });
1816
1803
  const venusApi = this.venusApi;
1817
1804
  if (!venusApi._mock.pendingRequests) {
1818
- console.log("[Venus Mock] Initializing pendingRequests");
1819
1805
  venusApi._mock.pendingRequests = {};
1820
1806
  }
1821
1807
  const requestId = Date.now().toString();
1822
- console.log("[Venus Mock] Creating request with ID:", requestId);
1823
1808
  return new Promise((resolve) => {
1824
1809
  venusApi._mock.pendingRequests[requestId] = { resolve };
1825
1810
  const id = notificationId || `mock-notification-${Date.now()}`;
@@ -1841,13 +1826,8 @@ var MockNotificationsApi = class {
1841
1826
  async setLocalNotificationsEnabled(enabled) {
1842
1827
  const venusApi = this.venusApi;
1843
1828
  if (isWebPlatform()) {
1844
- console.log(
1845
- "[Venus Mock] Set notifications enabled on web platform (simulated):",
1846
- enabled
1847
- );
1848
1829
  return true;
1849
1830
  }
1850
- console.log("[Venus Mock] Set local notifications enabled:", enabled);
1851
1831
  await createMockDelay(MOCK_DELAYS.short);
1852
1832
  venusApi._mock.notificationsEnabled = enabled;
1853
1833
  return enabled;
@@ -2072,16 +2052,20 @@ function initializePopups(venusApi, host) {
2072
2052
 
2073
2053
  // src/profile/HostProfileApi.ts
2074
2054
  var HostProfileApi = class {
2055
+ constructor(venusApi) {
2056
+ __publicField(this, "venusApi");
2057
+ this.venusApi = venusApi;
2058
+ }
2075
2059
  getCurrentProfile() {
2076
- const profile = window.venus?.profile;
2060
+ const profile = this.venusApi._profileData;
2077
2061
  if (!profile) {
2078
2062
  throw new Error(
2079
- "[Venus SDK] Host profile handshake did not complete. Await VenusAPI.initializeAsync() so INIT_SDK can deliver the profile before calling profile APIs."
2063
+ "[Venus SDK] Profile not available. You must await VenusAPI.initializeAsync() before calling getProfile(). INIT_SDK has not completed."
2080
2064
  );
2081
2065
  }
2082
2066
  if (!profile.id || !profile.username) {
2083
2067
  throw new Error(
2084
- "[Venus SDK] INIT_SDK returned an incomplete profile (missing id/username). The host must supply real credentials before rooms APIs are used."
2068
+ "[Venus SDK] INIT_SDK returned an incomplete profile (missing id/username). The host must supply valid profile data."
2085
2069
  );
2086
2070
  }
2087
2071
  return {
@@ -2095,6 +2079,10 @@ var HostProfileApi = class {
2095
2079
 
2096
2080
  // src/profile/MockProfileApi.ts
2097
2081
  var MockProfileApi = class {
2082
+ constructor(venusApi) {
2083
+ __publicField(this, "venusApi");
2084
+ this.venusApi = venusApi;
2085
+ }
2098
2086
  getCurrentProfile() {
2099
2087
  return {
2100
2088
  id: "mock_profile_123",
@@ -2107,11 +2095,22 @@ var MockProfileApi = class {
2107
2095
 
2108
2096
  // src/profile/index.ts
2109
2097
  function initializeProfile(venusApi, host) {
2098
+ venusApi.getProfile = () => {
2099
+ return host.profile.getCurrentProfile();
2100
+ };
2110
2101
  venusApi.getCurrentProfile = () => {
2102
+ console.warn(
2103
+ "[Venus SDK] DEPRECATED: VenusAPI.getCurrentProfile() is deprecated. Use VenusAPI.getProfile() instead. See migration guide: https://docs.venus.com/migration/profile-api"
2104
+ );
2111
2105
  return host.profile.getCurrentProfile();
2112
2106
  };
2113
2107
  }
2114
2108
 
2109
+ // src/utils/idGenerator.ts
2110
+ function generateId() {
2111
+ return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
2112
+ }
2113
+
2115
2114
  // src/rpc/RpcClient.ts
2116
2115
  var RpcClient = class {
2117
2116
  constructor() {
@@ -2154,7 +2153,7 @@ var RpcClient = class {
2154
2153
  }
2155
2154
  async call(method, args, timeout = 5e3) {
2156
2155
  return new Promise((resolve, reject) => {
2157
- const id = this.generateId();
2156
+ const id = generateId();
2158
2157
  this.addPendingCall(id, resolve, reject);
2159
2158
  const request = {
2160
2159
  type: "rpc-request",
@@ -2191,9 +2190,6 @@ var RpcClient = class {
2191
2190
  getPendingCall(id) {
2192
2191
  return this.pendingCalls.get(id);
2193
2192
  }
2194
- generateId() {
2195
- return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
2196
- }
2197
2193
  handleRpcResponse(response) {
2198
2194
  const pending = this.getPendingCall(response.id);
2199
2195
  if (!pending) {
@@ -2215,49 +2211,469 @@ var RpcClient = class {
2215
2211
  }
2216
2212
  };
2217
2213
 
2218
- // src/storage/MockStorageApi.ts
2219
- function createMockStorageApi(storageType, appUrl) {
2220
- const appIdentifier = appUrl ? generateAppIdentifier(appUrl) : null;
2221
- let prefix;
2222
- let syncDelay = 0;
2223
- switch (storageType) {
2224
- case "deviceCache":
2225
- prefix = "venus:app";
2226
- syncDelay = 0;
2227
- break;
2228
- case "appStorage":
2229
- prefix = "venus:app";
2230
- syncDelay = 100;
2231
- break;
2232
- case "globalStorage":
2233
- prefix = "venus:global";
2234
- syncDelay = 100;
2235
- break;
2236
- default:
2237
- throw new Error(`Unknown storage type: ${storageType}`);
2238
- }
2239
- prefix = storageType === "globalStorage" || !appIdentifier ? `${prefix}:` : `${prefix}:${appIdentifier}:`;
2240
- return new MockStorageApi(prefix, syncDelay);
2241
- }
2242
- var MockStorageApi = class {
2243
- constructor(prefix, syncDelay) {
2244
- __publicField(this, "prefix");
2245
- __publicField(this, "syncDelay");
2246
- this.prefix = prefix;
2247
- this.syncDelay = syncDelay;
2214
+ // src/rooms/VenusRoom.ts
2215
+ var VenusRoom = class {
2216
+ constructor(roomData) {
2217
+ __publicField(this, "id");
2218
+ __publicField(this, "name");
2219
+ __publicField(this, "players");
2220
+ __publicField(this, "maxPlayers");
2221
+ __publicField(this, "gameType");
2222
+ __publicField(this, "appId");
2223
+ __publicField(this, "type");
2224
+ __publicField(this, "createdBy");
2225
+ __publicField(this, "createdAt");
2226
+ __publicField(this, "updatedAt");
2227
+ __publicField(this, "isPrivate");
2228
+ __publicField(this, "status");
2229
+ __publicField(this, "customMetadata");
2230
+ __publicField(this, "admins");
2231
+ __publicField(this, "roomCode");
2232
+ __publicField(this, "description");
2233
+ __publicField(this, "data");
2234
+ __publicField(this, "version");
2235
+ this.id = roomData.id;
2236
+ this.name = roomData.name;
2237
+ this.players = Array.isArray(roomData.currentPlayers) ? [...roomData.currentPlayers] : [];
2238
+ this.maxPlayers = roomData.maxPlayers;
2239
+ this.gameType = roomData.gameType;
2240
+ this.appId = roomData.appId;
2241
+ this.type = roomData.type;
2242
+ this.createdBy = roomData.createdBy;
2243
+ this.createdAt = roomData.createdAt;
2244
+ this.updatedAt = roomData.updatedAt;
2245
+ this.isPrivate = roomData.isPrivate;
2246
+ this.status = roomData.status;
2247
+ this.customMetadata = roomData.customMetadata || {};
2248
+ this.admins = Array.isArray(roomData.admins) ? [...roomData.admins] : [];
2249
+ this.roomCode = roomData.roomCode;
2250
+ this.description = roomData.description;
2251
+ this.data = roomData.data || {};
2252
+ this.version = roomData.version;
2248
2253
  }
2249
- async clear() {
2250
- const fullLength = localStorage.length;
2251
- for (let i = 0; i < fullLength; i++) {
2252
- const fullKey = localStorage.key(i);
2253
- if (fullKey && fullKey.startsWith(this.prefix)) {
2254
- localStorage.removeItem(fullKey);
2255
- }
2254
+ };
2255
+
2256
+ // src/rooms/setupRoomNotifications.ts
2257
+ function invokeCallbacks(callbacks, event, context) {
2258
+ callbacks.forEach((callback) => {
2259
+ try {
2260
+ callback(event);
2261
+ } catch (error) {
2262
+ console.error(`[Venus SDK] Error in ${context} callback:`, error);
2263
+ throw error;
2256
2264
  }
2257
- await this.simulateSyncDelay();
2258
- }
2259
- async getAllItems() {
2260
- const items = new Array();
2265
+ });
2266
+ }
2267
+ function setupRoomNotifications(transport, getSubscriptions) {
2268
+ return transport.onVenusMessage((message) => {
2269
+ const subscriptions = getSubscriptions();
2270
+ if (!subscriptions) {
2271
+ return;
2272
+ }
2273
+ if (message.type === "H5_ROOM_DATA_UPDATED") {
2274
+ const messageData = message.data;
2275
+ const { roomId, roomData } = messageData;
2276
+ if (!roomId) return;
2277
+ const callbacks = subscriptions.data[roomId] || [];
2278
+ const event = {
2279
+ type: "H5_ROOM_DATA_UPDATED",
2280
+ roomId,
2281
+ roomData,
2282
+ timestamp: messageData.timestamp
2283
+ };
2284
+ invokeCallbacks(callbacks, event, "room data");
2285
+ }
2286
+ if (message.type === "H5_ROOM_MESSAGE_RECEIVED" || message.type === "H5_ROOM_MESSAGE_UPDATED" || message.type === "H5_ROOM_MESSAGE_DELETED") {
2287
+ const messageData = message.data;
2288
+ const { roomId } = messageData;
2289
+ if (!roomId) return;
2290
+ const callbacks = subscriptions.messages[roomId] || [];
2291
+ const event = {
2292
+ type: message.type,
2293
+ roomId,
2294
+ message: messageData.message,
2295
+ timestamp: messageData.timestamp
2296
+ };
2297
+ invokeCallbacks(callbacks, event, "room message");
2298
+ }
2299
+ if (message.type === "app:h5:proposedMoveValidationUpdated") {
2300
+ const messageData = message.data;
2301
+ const { roomId } = messageData;
2302
+ if (!roomId) return;
2303
+ const callbacks = subscriptions.gameEvents[roomId] || [];
2304
+ const event = {
2305
+ type: "app:h5:proposedMoveValidationUpdated",
2306
+ roomId,
2307
+ proposedMoveData: messageData.proposedMoveData,
2308
+ proposedMoveId: messageData.proposedMoveId,
2309
+ changeType: messageData.changeType,
2310
+ timestamp: messageData.timestamp
2311
+ };
2312
+ invokeCallbacks(callbacks, event, "game event");
2313
+ }
2314
+ });
2315
+ }
2316
+
2317
+ // src/rooms/RpcRoomsApi.ts
2318
+ var RpcRoomsApi = class {
2319
+ constructor(rpcClient) {
2320
+ __publicField(this, "rpcClient");
2321
+ __publicField(this, "subscriptions");
2322
+ this.rpcClient = rpcClient;
2323
+ this.subscriptions = {
2324
+ data: {},
2325
+ messages: {},
2326
+ gameEvents: {}
2327
+ };
2328
+ }
2329
+ /**
2330
+ * Get the subscription state for external access (used by setupRoomNotifications)
2331
+ */
2332
+ getSubscriptions() {
2333
+ return this.subscriptions;
2334
+ }
2335
+ /**
2336
+ * Set up room notification routing from the transport
2337
+ */
2338
+ setupNotifications(transport) {
2339
+ setupRoomNotifications(transport, () => this.getSubscriptions());
2340
+ }
2341
+ async createRoomAsync(options) {
2342
+ const response = await this.rpcClient.call(
2343
+ "H5_ROOM_CREATE" /* H5_ROOM_CREATE */,
2344
+ {
2345
+ options
2346
+ }
2347
+ );
2348
+ if (response.success === false) {
2349
+ const errorMessage = typeof response.error === "string" ? response.error : "Failed to create room";
2350
+ throw new Error(errorMessage);
2351
+ }
2352
+ const room = new VenusRoom(response.roomData);
2353
+ return room;
2354
+ }
2355
+ async joinOrCreateRoomAsync(options) {
2356
+ const response = await this.rpcClient.call(
2357
+ "H5_ROOM_JOIN_OR_CREATE" /* H5_ROOM_JOIN_OR_CREATE */,
2358
+ {
2359
+ options
2360
+ }
2361
+ );
2362
+ if (response.success === false) {
2363
+ const errorMessage = typeof response.error === "string" ? response.error : "Failed to join or create room";
2364
+ throw new Error(errorMessage);
2365
+ }
2366
+ const room = new VenusRoom(response.value.roomData);
2367
+ return {
2368
+ action: response.value.action,
2369
+ room,
2370
+ playersJoined: response.value.playersJoined
2371
+ };
2372
+ }
2373
+ async joinRoomByCodeAsync(roomCode) {
2374
+ const response = await this.rpcClient.call(
2375
+ "H5_ROOM_JOIN_BY_CODE" /* H5_ROOM_JOIN_BY_CODE */,
2376
+ {
2377
+ roomCode
2378
+ }
2379
+ );
2380
+ if (response?.success === false) {
2381
+ const errorMessage = typeof response.error === "string" ? response.error : "Failed to join room by code";
2382
+ throw new Error(errorMessage);
2383
+ }
2384
+ const room = new VenusRoom(response.roomData);
2385
+ return room;
2386
+ }
2387
+ // Get user's rooms with optional filtering
2388
+ async getUserRoomsAsync(options = {}) {
2389
+ const response = await this.rpcClient.call(
2390
+ "H5_ROOM_GET_USER_ROOMS" /* H5_ROOM_GET_USER_ROOMS */,
2391
+ {
2392
+ includeArchived: options.includeArchived ?? false
2393
+ }
2394
+ );
2395
+ if (response?.success === false) {
2396
+ const errorMessage = typeof response.error === "string" ? response.error : "Failed to get user rooms";
2397
+ throw new Error(errorMessage);
2398
+ }
2399
+ const venusRooms = [];
2400
+ for (const roomData of response.rooms) {
2401
+ if (!roomData.id) {
2402
+ console.warn("[Venus SDK] getUserRooms: Skipping room with missing ID:", roomData);
2403
+ continue;
2404
+ }
2405
+ try {
2406
+ const venusRoom = new VenusRoom(roomData);
2407
+ venusRooms.push(venusRoom);
2408
+ } catch (error) {
2409
+ console.warn(
2410
+ "[Venus SDK] getUserRooms: Failed to create VenusRoom object:",
2411
+ error,
2412
+ roomData
2413
+ );
2414
+ }
2415
+ }
2416
+ return venusRooms;
2417
+ }
2418
+ async updateRoomDataAsync(room, updates, options = {}) {
2419
+ const response = await this.rpcClient.call(
2420
+ "H5_ROOM_UPDATE_DATA" /* H5_ROOM_UPDATE_DATA */,
2421
+ {
2422
+ roomId: room.id,
2423
+ updates,
2424
+ merge: options.merge ?? true
2425
+ }
2426
+ );
2427
+ if (response?.success === false) {
2428
+ const errorMessage = typeof response.error === "string" ? response.error : "Failed to update room data";
2429
+ throw new Error(errorMessage);
2430
+ }
2431
+ }
2432
+ async getRoomDataAsync(room) {
2433
+ const response = await this.rpcClient.call(
2434
+ "H5_ROOM_GET_DATA" /* H5_ROOM_GET_DATA */,
2435
+ {
2436
+ roomId: room.id
2437
+ }
2438
+ );
2439
+ if (response?.success === false) {
2440
+ const errorMessage = typeof response.error === "string" ? response.error : "Failed to get room data";
2441
+ throw new Error(errorMessage);
2442
+ }
2443
+ return response.data;
2444
+ }
2445
+ async sendRoomMessageAsync(venusRoom, request) {
2446
+ const response = await this.rpcClient.call(
2447
+ "H5_ROOM_SEND_MESSAGE" /* H5_ROOM_SEND_MESSAGE */,
2448
+ {
2449
+ roomId: venusRoom.id,
2450
+ message: request.message,
2451
+ metadata: request.metadata
2452
+ }
2453
+ );
2454
+ if (response?.success === false) {
2455
+ const errorMessage = typeof response.error === "string" ? response.error : "Failed to send message";
2456
+ throw new Error(errorMessage);
2457
+ }
2458
+ return response.messageId;
2459
+ }
2460
+ async leaveRoomAsync(room) {
2461
+ const response = await this.rpcClient.call(
2462
+ "H5_ROOM_LEAVE" /* H5_ROOM_LEAVE */,
2463
+ {
2464
+ roomId: room.id
2465
+ }
2466
+ );
2467
+ if (response?.success === false) {
2468
+ const errorMessage = typeof response.error === "string" ? response.error : "Failed to leave room";
2469
+ throw new Error(errorMessage);
2470
+ }
2471
+ }
2472
+ async startRoomGameAsync(room, options = {}) {
2473
+ const response = await this.rpcClient.call(
2474
+ "H5_ROOM_START_GAME" /* H5_ROOM_START_GAME */,
2475
+ {
2476
+ roomId: room.id,
2477
+ gameConfig: options.gameConfig ?? {},
2478
+ turnOrder: options.turnOrder ?? null
2479
+ }
2480
+ );
2481
+ if (response?.success === false) {
2482
+ const errorMessage = typeof response.error === "string" ? response.error : "Failed to start game";
2483
+ throw new Error(errorMessage);
2484
+ }
2485
+ }
2486
+ async proposeMoveAsync(room, proposalPayload) {
2487
+ const response = await this.rpcClient.call(
2488
+ "h5:room:proposeMove" /* H5_ROOM_PROPOSE_MOVE */,
2489
+ {
2490
+ roomId: room.id,
2491
+ gameSpecificState: proposalPayload.gameSpecificState,
2492
+ moveType: proposalPayload.moveType,
2493
+ clientContext: proposalPayload.clientContext,
2494
+ clientProposalId: proposalPayload.clientProposalId
2495
+ }
2496
+ );
2497
+ if (response?.success === false) {
2498
+ const errorMessage = typeof response.error === "string" ? response.error : "Failed to propose move";
2499
+ throw new Error(errorMessage);
2500
+ }
2501
+ return response.data;
2502
+ }
2503
+ async validateMoveAsync(_room, moveId, verdict) {
2504
+ return {
2505
+ success: true,
2506
+ moveId,
2507
+ isValid: verdict.isValid,
2508
+ reason: verdict.reason
2509
+ };
2510
+ }
2511
+ async subscribeAsync(room, options = {}) {
2512
+ const roomId = room.id;
2513
+ const existingData = this.subscriptions.data[roomId];
2514
+ const existingMessages = this.subscriptions.messages[roomId];
2515
+ const existingGameEvents = this.subscriptions.gameEvents[roomId];
2516
+ const subscribeToData = Boolean(options.onData) && (existingData?.length ?? 0) === 0;
2517
+ const subscribeToMessages = Boolean(options.onMessages) && (existingMessages?.length ?? 0) === 0;
2518
+ const subscribeToProposedMoves = Boolean(options.onGameEvents) && (existingGameEvents?.length ?? 0) === 0;
2519
+ if (subscribeToData || subscribeToMessages || subscribeToProposedMoves) {
2520
+ try {
2521
+ await this.rpcClient.call("H5_ROOM_SUBSCRIBE" /* H5_ROOM_SUBSCRIBE */, {
2522
+ roomId,
2523
+ subscribeToData,
2524
+ subscribeToMessages,
2525
+ subscribeToProposedMoves
2526
+ });
2527
+ } catch (error) {
2528
+ console.error("[Venus SDK] Failed to set up room subscription:", error);
2529
+ throw error;
2530
+ }
2531
+ }
2532
+ if (options.onData) {
2533
+ if (!this.subscriptions.data[roomId]) {
2534
+ this.subscriptions.data[roomId] = [];
2535
+ }
2536
+ this.subscriptions.data[roomId].push(options.onData);
2537
+ }
2538
+ if (options.onMessages) {
2539
+ if (!this.subscriptions.messages[roomId]) {
2540
+ this.subscriptions.messages[roomId] = [];
2541
+ }
2542
+ this.subscriptions.messages[roomId].push(options.onMessages);
2543
+ }
2544
+ if (options.onGameEvents) {
2545
+ if (!this.subscriptions.gameEvents[roomId]) {
2546
+ this.subscriptions.gameEvents[roomId] = [];
2547
+ }
2548
+ this.subscriptions.gameEvents[roomId].push(options.onGameEvents);
2549
+ }
2550
+ let disposed = false;
2551
+ return () => {
2552
+ if (disposed) return;
2553
+ disposed = true;
2554
+ if (options.onData) {
2555
+ const callbacks = this.subscriptions.data[roomId];
2556
+ if (callbacks) {
2557
+ const index = callbacks.indexOf(options.onData);
2558
+ if (index > -1) {
2559
+ callbacks.splice(index, 1);
2560
+ }
2561
+ }
2562
+ }
2563
+ if (options.onMessages) {
2564
+ const callbacks = this.subscriptions.messages[roomId];
2565
+ if (callbacks) {
2566
+ const index = callbacks.indexOf(options.onMessages);
2567
+ if (index > -1) {
2568
+ callbacks.splice(index, 1);
2569
+ }
2570
+ }
2571
+ }
2572
+ if (options.onGameEvents) {
2573
+ const callbacks = this.subscriptions.gameEvents[roomId];
2574
+ if (callbacks) {
2575
+ const index = callbacks.indexOf(options.onGameEvents);
2576
+ if (index > -1) {
2577
+ callbacks.splice(index, 1);
2578
+ }
2579
+ }
2580
+ }
2581
+ const hasAnySubscriptions = (this.subscriptions.data[roomId]?.length ?? 0) > 0 || (this.subscriptions.messages[roomId]?.length ?? 0) > 0 || (this.subscriptions.gameEvents[roomId]?.length ?? 0) > 0;
2582
+ if (!hasAnySubscriptions) {
2583
+ this.rpcClient.call("H5_ROOM_UNSUBSCRIBE" /* H5_ROOM_UNSUBSCRIBE */, {
2584
+ roomId
2585
+ }).catch((error) => {
2586
+ console.error("[Venus SDK] Failed to clean up room subscription:", error);
2587
+ });
2588
+ }
2589
+ };
2590
+ }
2591
+ };
2592
+
2593
+ // src/rooms/index.ts
2594
+ function bindMethod(target, targetKey, source, sourceKey) {
2595
+ const key = sourceKey ?? targetKey;
2596
+ const fn = source?.[key];
2597
+ if (typeof fn === "function") {
2598
+ target[targetKey] = fn.bind(source);
2599
+ return true;
2600
+ }
2601
+ return false;
2602
+ }
2603
+ function initializeRoomsApi(venusApi, host) {
2604
+ const roomsApi = host?.rooms;
2605
+ if (!roomsApi) {
2606
+ console.warn(
2607
+ "[Venus SDK] Host did not provide a rooms implementation. Rooms API will be unavailable."
2608
+ );
2609
+ return;
2610
+ }
2611
+ const venus = venusApi;
2612
+ const existingNamespace = venus.rooms || {};
2613
+ const roomsNamespace = Object.assign({}, existingNamespace);
2614
+ const namespaceBindings = [
2615
+ ["createRoomAsync"],
2616
+ ["joinOrCreateRoomAsync"],
2617
+ ["joinRoomByCodeAsync"],
2618
+ ["getUserRoomsAsync"],
2619
+ ["subscribeAsync"],
2620
+ ["updateRoomDataAsync"],
2621
+ ["getRoomDataAsync"],
2622
+ ["sendRoomMessageAsync"],
2623
+ ["leaveRoomAsync"],
2624
+ ["startRoomGameAsync"],
2625
+ ["proposeMoveAsync"],
2626
+ ["validateMoveAsync"]
2627
+ ];
2628
+ namespaceBindings.forEach(([targetKey, sourceKey]) => {
2629
+ bindMethod(roomsNamespace, targetKey, roomsApi, sourceKey);
2630
+ });
2631
+ venus.rooms = roomsNamespace;
2632
+ }
2633
+
2634
+ // src/storage/MockStorageApi.ts
2635
+ function createMockStorageApi(storageType, appUrl) {
2636
+ const appIdentifier = appUrl ? generateAppIdentifier(appUrl) : null;
2637
+ let prefix;
2638
+ let syncDelay = 0;
2639
+ switch (storageType) {
2640
+ case "deviceCache":
2641
+ prefix = "venus:app";
2642
+ syncDelay = 0;
2643
+ break;
2644
+ case "appStorage":
2645
+ prefix = "venus:app";
2646
+ syncDelay = 100;
2647
+ break;
2648
+ case "globalStorage":
2649
+ prefix = "venus:global";
2650
+ syncDelay = 100;
2651
+ break;
2652
+ default:
2653
+ throw new Error(`Unknown storage type: ${storageType}`);
2654
+ }
2655
+ prefix = storageType === "globalStorage" || !appIdentifier ? `${prefix}:` : `${prefix}:${appIdentifier}:`;
2656
+ return new MockStorageApi(prefix, syncDelay);
2657
+ }
2658
+ var MockStorageApi = class {
2659
+ constructor(prefix, syncDelay) {
2660
+ __publicField(this, "prefix");
2661
+ __publicField(this, "syncDelay");
2662
+ this.prefix = prefix;
2663
+ this.syncDelay = syncDelay;
2664
+ }
2665
+ async clear() {
2666
+ const fullLength = localStorage.length;
2667
+ for (let i = 0; i < fullLength; i++) {
2668
+ const fullKey = localStorage.key(i);
2669
+ if (fullKey && fullKey.startsWith(this.prefix)) {
2670
+ localStorage.removeItem(fullKey);
2671
+ }
2672
+ }
2673
+ await this.simulateSyncDelay();
2674
+ }
2675
+ async getAllItems() {
2676
+ const items = new Array();
2261
2677
  const fullLength = localStorage.length;
2262
2678
  for (let i = 0; i < fullLength; i++) {
2263
2679
  const fullKey = localStorage.key(i);
@@ -2448,24 +2864,20 @@ function initializeStorage(venusApiInstance, host) {
2448
2864
  venusApiInstance.globalStorage = host.globalStorage;
2449
2865
  }
2450
2866
 
2451
- // src/simulation/utils.ts
2452
- function sumContributions(contributions) {
2453
- const totals = {};
2454
- for (const profileId in contributions) {
2455
- for (const entityId in contributions[profileId]) {
2456
- const amount = contributions[profileId][entityId] || 0;
2457
- totals[entityId] = (totals[entityId] || 0) + amount;
2458
- }
2459
- }
2460
- return totals;
2461
- }
2462
-
2463
2867
  // src/simulation/RpcSimulationApi.ts
2464
2868
  var RpcSimulationApi = class {
2465
2869
  constructor(rpcClient) {
2466
2870
  __publicField(this, "rpcClient");
2467
2871
  __publicField(this, "_simulationConfig", null);
2872
+ __publicField(this, "subscriptionCallbacks", /* @__PURE__ */ new Map());
2468
2873
  this.rpcClient = rpcClient;
2874
+ this.rpcClient.onNotification(
2875
+ "H5_SIMULATION_UPDATE" /* H5_SIMULATION_UPDATE */,
2876
+ this.handleSimulationUpdate.bind(this)
2877
+ );
2878
+ }
2879
+ isEnabled() {
2880
+ return true;
2469
2881
  }
2470
2882
  async validateSlotAssignmentAsync(containerId, slotId, itemId) {
2471
2883
  return this.rpcClient.call(
@@ -2477,14 +2889,47 @@ var RpcSimulationApi = class {
2477
2889
  }
2478
2890
  );
2479
2891
  }
2480
- sumContributions(contributions) {
2481
- return sumContributions(contributions);
2892
+ async subscribeAsync(options) {
2893
+ this.ensureValidSubscribeOptions(options);
2894
+ const subscriptionId = generateId();
2895
+ this.subscriptionCallbacks.set(subscriptionId, options.onUpdate);
2896
+ try {
2897
+ await this.rpcClient.call("H5_SIMULATION_SUBSCRIBE" /* H5_SIMULATION_SUBSCRIBE */, {
2898
+ subscriptionId,
2899
+ entities: options.entities,
2900
+ tags: options.tags,
2901
+ activeRuns: options.activeRuns,
2902
+ roomId: options.roomId
2903
+ });
2904
+ } catch (error) {
2905
+ this.subscriptionCallbacks.delete(subscriptionId);
2906
+ throw error;
2907
+ }
2908
+ let unsubscribed = false;
2909
+ return () => {
2910
+ if (unsubscribed) {
2911
+ return;
2912
+ }
2913
+ unsubscribed = true;
2914
+ this.subscriptionCallbacks.delete(subscriptionId);
2915
+ void this.rpcClient.call("H5_SIMULATION_UNSUBSCRIBE" /* H5_SIMULATION_UNSUBSCRIBE */, {
2916
+ subscriptionId
2917
+ }).catch((error) => {
2918
+ console.error(
2919
+ "[Venus SDK] Failed to unsubscribe simulation listener",
2920
+ error
2921
+ );
2922
+ });
2923
+ };
2482
2924
  }
2483
2925
  executeBatchOperationsAsync(operations, validateOnly) {
2484
- return this.rpcClient.call("H5_SIMULATION_BATCH_OPERATIONS" /* H5_SIMULATION_BATCH_OPERATIONS */, {
2485
- operations,
2486
- validateOnly
2487
- });
2926
+ return this.rpcClient.call(
2927
+ "H5_SIMULATION_BATCH_OPERATIONS" /* H5_SIMULATION_BATCH_OPERATIONS */,
2928
+ {
2929
+ operations,
2930
+ validateOnly
2931
+ }
2932
+ );
2488
2933
  }
2489
2934
  async getAvailableItemsAsync(containerId, slotId) {
2490
2935
  const response = await this.rpcClient.call(
@@ -2507,17 +2952,23 @@ var RpcSimulationApi = class {
2507
2952
  );
2508
2953
  }
2509
2954
  assignItemToSlotAsync(containerId, slotId, itemId) {
2510
- return this.rpcClient.call("H5_SIMULATION_ASSIGN_ITEM" /* H5_SIMULATION_ASSIGN_ITEM */, {
2511
- containerId,
2512
- slotId,
2513
- itemId
2514
- });
2955
+ return this.rpcClient.call(
2956
+ "H5_SIMULATION_ASSIGN_ITEM" /* H5_SIMULATION_ASSIGN_ITEM */,
2957
+ {
2958
+ containerId,
2959
+ slotId,
2960
+ itemId
2961
+ }
2962
+ );
2515
2963
  }
2516
2964
  removeItemFromSlotAsync(containerId, slotId) {
2517
- return this.rpcClient.call("H5_SIMULATION_REMOVE_ITEM" /* H5_SIMULATION_REMOVE_ITEM */, {
2518
- containerId,
2519
- slotId
2520
- });
2965
+ return this.rpcClient.call(
2966
+ "H5_SIMULATION_REMOVE_ITEM" /* H5_SIMULATION_REMOVE_ITEM */,
2967
+ {
2968
+ containerId,
2969
+ slotId
2970
+ }
2971
+ );
2521
2972
  }
2522
2973
  async getSlotContainersAsync() {
2523
2974
  const response = await this.rpcClient.call(
@@ -2542,7 +2993,6 @@ var RpcSimulationApi = class {
2542
2993
  roomId
2543
2994
  }
2544
2995
  );
2545
- console.log("[Venus SDK] getStateAsync", response);
2546
2996
  if (response.configuration) {
2547
2997
  this._simulationConfig = response.configuration;
2548
2998
  }
@@ -2554,9 +3004,10 @@ var RpcSimulationApi = class {
2554
3004
  }
2555
3005
  const config = await this.rpcClient.call(
2556
3006
  "H5_SIMULATION_GET_CONFIG" /* H5_SIMULATION_GET_CONFIG */,
2557
- {}
3007
+ {
3008
+ roomId
3009
+ }
2558
3010
  );
2559
- console.log("[Venus SDK] getConfigAsync", config);
2560
3011
  if (config) {
2561
3012
  this._simulationConfig = config;
2562
3013
  return config;
@@ -2564,14 +3015,17 @@ var RpcSimulationApi = class {
2564
3015
  throw new Error("No simulation configuration available");
2565
3016
  }
2566
3017
  executeRecipeAsync(recipeId, inputs, options) {
2567
- return this.rpcClient.call("H5_SIMULATION_EXECUTE_RECIPE" /* H5_SIMULATION_EXECUTE_RECIPE */, {
2568
- recipeId,
2569
- inputs,
2570
- roomId: options?.roomId,
2571
- batchAmount: options?.batchAmount,
2572
- allowPartialBatch: options?.allowPartialBatch,
2573
- entity: options?.entity
2574
- });
3018
+ return this.rpcClient.call(
3019
+ "H5_SIMULATION_EXECUTE_RECIPE" /* H5_SIMULATION_EXECUTE_RECIPE */,
3020
+ {
3021
+ recipeId,
3022
+ inputs,
3023
+ roomId: options?.roomId,
3024
+ batchAmount: options?.batchAmount,
3025
+ allowPartialBatch: options?.allowPartialBatch,
3026
+ entity: options?.entity
3027
+ }
3028
+ );
2575
3029
  }
2576
3030
  collectRecipeAsync(runId) {
2577
3031
  return this.rpcClient.call("H5_SIMULATION_COLLECT_RECIPE" /* H5_SIMULATION_COLLECT_RECIPE */, {
@@ -2579,9 +3033,12 @@ var RpcSimulationApi = class {
2579
3033
  });
2580
3034
  }
2581
3035
  getActiveRunsAsync(options) {
2582
- return this.rpcClient.call("H5_SIMULATION_GET_ACTIVE_RUNS" /* H5_SIMULATION_GET_ACTIVE_RUNS */, {
2583
- roomId: options?.roomId
2584
- });
3036
+ return this.rpcClient.call(
3037
+ "H5_SIMULATION_GET_ACTIVE_RUNS" /* H5_SIMULATION_GET_ACTIVE_RUNS */,
3038
+ {
3039
+ roomId: options?.roomId
3040
+ }
3041
+ );
2585
3042
  }
2586
3043
  executeScopedRecipeAsync(recipeId, entity, inputs, options) {
2587
3044
  return this.rpcClient.call(
@@ -2599,635 +3056,104 @@ var RpcSimulationApi = class {
2599
3056
  return this.rpcClient.call(
2600
3057
  "H5_SIMULATION_GET_AVAILABLE_RECIPES" /* H5_SIMULATION_GET_AVAILABLE_RECIPES */,
2601
3058
  {
2602
- roomId: options?.roomId || null,
2603
- includeActorRecipes: options?.includeActorRecipes || false
2604
- }
2605
- );
2606
- }
2607
- getRecipeRequirementsAsync(recipe) {
2608
- return this.rpcClient.call(
2609
- "H5_SIMULATION_GET_RECIPE_REQUIREMENTS" /* H5_SIMULATION_GET_RECIPE_REQUIREMENTS */,
2610
- {
2611
- recipeId: recipe.recipeId,
2612
- entity: recipe.entity,
2613
- batchAmount: recipe.batchAmount
2614
- }
2615
- );
2616
- }
2617
- getBatchRecipeRequirementsAsync(recipes) {
2618
- return this.rpcClient.call(
2619
- "H5_SIMULATION_GET_BATCH_RECIPE_REQUIREMENTS" /* H5_SIMULATION_GET_BATCH_RECIPE_REQUIREMENTS */,
2620
- {
2621
- recipes
2622
- }
2623
- );
2624
- }
2625
- triggerRecipeChainAsync(recipeId, options) {
2626
- return this.rpcClient.call(
2627
- "H5_SIMULATION_TRIGGER_RECIPE_CHAIN" /* H5_SIMULATION_TRIGGER_RECIPE_CHAIN */,
2628
- {
2629
- triggerRecipeId: recipeId,
2630
- context: options?.context,
2631
- roomId: options?.roomId
2632
- }
2633
- );
2634
- }
2635
- getEntityMetadataAsync(entityId) {
2636
- return this.rpcClient.call(
2637
- "H5_SIMULATION_GET_ENTITY_METADATA" /* H5_SIMULATION_GET_ENTITY_METADATA */,
2638
- {
2639
- entityId
2640
- }
2641
- );
2642
- }
2643
- async resolveFieldValueAsync(entityId, fieldPath, entity) {
2644
- const response = await this.rpcClient.call(
2645
- "H5_SIMULATION_RESOLVE_VALUE" /* H5_SIMULATION_RESOLVE_VALUE */,
2646
- {
2647
- entityId,
2648
- fieldPath,
2649
- entity
2650
- }
2651
- );
2652
- return response.value;
2653
- }
2654
- };
2655
-
2656
- // src/simulation/MockSimulationApi.ts
2657
- function generateAppIdentifier2() {
2658
- if (typeof window === "undefined") return "unknown-app";
2659
- const url = window.location.href;
2660
- const match = url.match(/\/H5\/([^\/]+)/);
2661
- return match ? match[1] : "unknown-app";
2662
- }
2663
- var MockSimulationApi = class {
2664
- constructor(simulationConfig = null) {
2665
- __publicField(this, "mockSimulationConfigs", /* @__PURE__ */ new Map());
2666
- // appIdentifier -> config
2667
- __publicField(this, "mockSimulationStates", /* @__PURE__ */ new Map());
2668
- // appIdentifier -> config
2669
- __publicField(this, "mockActiveTimers", /* @__PURE__ */ new Map());
2670
- // appIdentifier -> timers[]
2671
- __publicField(this, "appId");
2672
- __publicField(this, "providedSimulationConfig");
2673
- this.appId = generateAppIdentifier2();
2674
- this.providedSimulationConfig = simulationConfig;
2675
- }
2676
- sumContributions(contributions) {
2677
- return sumContributions(contributions);
2678
- }
2679
- async validateSlotAssignmentAsync(containerId, slotId, itemId) {
2680
- this.log("validateSlotAssignmentAsync called:", {
2681
- containerId,
2682
- slotId,
2683
- itemId
2684
- });
2685
- return { valid: true, message: "Mock validation successful" };
2686
- }
2687
- async executeBatchOperationsAsync(operations, validateOnly) {
2688
- this.log("executeBatchOperationsAsync called:", {
2689
- operations,
2690
- validateOnly
2691
- });
2692
- return {
2693
- success: true,
2694
- results: operations.map(() => ({ success: true }))
2695
- };
2696
- }
2697
- async getAvailableItemsAsync(containerId, slotId) {
2698
- console.log("[Venus Simulation Mock] getAvailableItemsAsync called:", {
2699
- containerId,
2700
- slotId
2701
- });
2702
- const appIdentifier = generateAppIdentifier2();
2703
- const mockSimulationConfigs = this.mockSimulationConfigs;
2704
- const config = mockSimulationConfigs.get(appIdentifier) || {
2705
- entities: {}
2706
- };
2707
- const availableItems = Object.entries(config.entities).slice(0, 3).map(([entityId, entity]) => ({
2708
- entityId,
2709
- quantity: 1,
2710
- metadata: entity.metadata,
2711
- powerPreview: 100
2712
- // Mock power value
2713
- }));
2714
- return availableItems;
2715
- }
2716
- async calculatePowerPreviewAsync(containerId, slotId, candidateItemId) {
2717
- this.log("calculatePowerPreviewAsync called:", {
2718
- containerId,
2719
- slotId,
2720
- candidateItemId
2721
- });
2722
- return {
2723
- currentPower: 1e3,
2724
- previewPower: 1200,
2725
- powerDelta: 200,
2726
- breakdown: { base: 800, weapon: 200, armor: 200 }
2727
- };
2728
- }
2729
- async getSlotContainersAsync() {
2730
- this.log("getSlotContainersAsync called");
2731
- const appIdentifier = this.appId;
2732
- const mockSimulationConfigs = this.mockSimulationConfigs;
2733
- const config = mockSimulationConfigs.get(appIdentifier) || {
2734
- entities: {}
2735
- };
2736
- const containers = Object.entries(config.entities).filter(([_, entity]) => entity.metadata?.slots).map(([entityId, entity]) => ({
2737
- entityId,
2738
- slots: entity.metadata?.slots,
2739
- isOwned: true
2740
- // Mock: assume all containers are owned
2741
- }));
2742
- return containers;
2743
- }
2744
- async getSlotAssignmentsAsync(containerId) {
2745
- this.log("getSlotAssignmentsAsync called for:", containerId);
2746
- return [];
2747
- }
2748
- async resolveFieldValueAsync(entityId, fieldPath, entity) {
2749
- this.log("resolveFieldValueAsync called:", {
2750
- entityId,
2751
- fieldPath,
2752
- entity
2753
- });
2754
- const mockValues = {
2755
- basePower: 850,
2756
- weaponPower: 300,
2757
- armorPower: 150,
2758
- total_power: 1300,
2759
- total_defense_power: 5e3
2760
- };
2761
- return mockValues[fieldPath] || 100;
2762
- }
2763
- async getEntityMetadataAsync(entityId) {
2764
- this.log("getEntityMetadataAsync called for:", entityId);
2765
- const mockSimulationConfigs = this.mockSimulationConfigs;
2766
- const appIdentifier = this.appId;
2767
- const config = mockSimulationConfigs.get(
2768
- appIdentifier
2769
- ) || {
2770
- entities: {}};
2771
- const entity = config.entities[entityId];
2772
- return entity?.metadata || {};
2773
- }
2774
- async collectRecipeAsync(runId) {
2775
- this.log("collectRecipeAsync called:", { runId });
2776
- const mockRewards = {
2777
- cash: Math.floor(Math.random() * 1e3) + 500,
2778
- experience: Math.floor(Math.random() * 50) + 25
2779
- };
2780
- return {
2781
- success: true,
2782
- runId,
2783
- rewards: mockRewards,
2784
- message: "Rewards collected successfully"
2785
- };
2786
- }
2787
- executeRecipeAsync(recipeId, inputs, options) {
2788
- this.log("executeRecipeAsync called:", {
2789
- recipeId,
2790
- inputs,
2791
- options
2792
- });
2793
- const appIdentifier = this.appId;
2794
- return this.executeRecipe(appIdentifier, recipeId, inputs);
2795
- }
2796
- async executeScopedRecipeAsync(recipeId, entity, inputs, options) {
2797
- this.log("executeScopedRecipeAsync called:", {
2798
- recipeId,
2799
- entity,
2800
- inputs,
2801
- roomId: options?.roomId,
2802
- options
2803
- });
2804
- return {
2805
- success: true,
2806
- message: "Mock scoped recipe execution successful"
2807
- };
2808
- }
2809
- async getActiveRunsAsync(options) {
2810
- this.log("getActiveRunsAsync called:", options);
2811
- const appIdentifier = this.appId;
2812
- let state = this.mockSimulationStates.get(appIdentifier);
2813
- if (!state) {
2814
- state = await this.initializeSimulationState(appIdentifier);
2815
- }
2816
- return state.activeRuns || [];
2817
- }
2818
- async getAvailableRecipesAsync(options) {
2819
- this.log("getAvailableRecipesAsync called:", options);
2820
- const baseRecipes = [
2821
- { id: "collect_resources", scope: "player", clientViewable: true },
2822
- { id: "upgrade_equipment", scope: "player", clientViewable: true }
2823
- ];
2824
- if (options?.roomId) {
2825
- baseRecipes.push(
2826
- { id: "room_upgrade", scope: "room", clientViewable: true },
2827
- { id: "cooperative_project", scope: "room", clientViewable: true }
2828
- );
2829
- }
2830
- if (options?.includeActorRecipes && options?.roomId) {
2831
- baseRecipes.push(
2832
- { id: "trade_with_npc", scope: "actor", clientViewable: true },
2833
- { id: "attack_monster", scope: "actor", clientViewable: true }
2834
- );
2835
- }
2836
- return { success: true, recipes: baseRecipes };
2837
- }
2838
- async getBatchRecipeRequirementsAsync(recipes) {
2839
- this.log("getBatchRecipeRequirementsAsync called:", {
2840
- count: recipes?.length
2841
- });
2842
- const results = (recipes || []).map((q) => ({
2843
- recipeId: q.recipeId,
2844
- entity: q.entity || null,
2845
- amount: q.batchAmount || 1,
2846
- inputs: { cash: "BE:0" },
2847
- canAfford: true,
2848
- disabled: false
2849
- }));
2850
- return { success: true, results };
2851
- }
2852
- async getRecipeRequirementsAsync(recipe) {
2853
- this.log("getRecipeRequirementsAsync called:", recipe);
2854
- return {
2855
- recipeId: recipe.recipeId,
2856
- entity: recipe.entity || null,
2857
- amount: recipe.batchAmount,
2858
- inputs: { cash: "BE:0" },
2859
- canAfford: true,
2860
- disabled: false
2861
- };
2862
- }
2863
- async triggerRecipeChainAsync(recipeId, options) {
2864
- this.log("triggerRecipeChainAsync called:", { recipeId, ...options });
2865
- return {
2866
- success: true,
2867
- message: "Mock recipe chain triggered successfully"
2868
- };
2869
- }
2870
- log(message, ...args) {
2871
- console.log(`[Venus Sim Mock] ${message}`, args);
2872
- }
2873
- async executeRecipe(appIdentifier, recipeId, inputs) {
2874
- this.log(`Executing recipe ${recipeId} for ${appIdentifier}`, inputs);
2875
- const mockSimulationConfigs = this.mockSimulationConfigs;
2876
- const mockSimulationStates = this.mockSimulationStates;
2877
- let config = mockSimulationConfigs.get(appIdentifier);
2878
- let state = mockSimulationStates.get(appIdentifier);
2879
- if (!config || !state) {
2880
- state = await this.initializeSimulationState(appIdentifier);
2881
- config = mockSimulationConfigs.get(appIdentifier);
2882
- if (!config) {
2883
- throw new Error("Failed to initialize simulation config");
2884
- }
2885
- }
2886
- const recipe = config.recipes?.[recipeId];
2887
- if (!recipe) {
2888
- throw new Error(`Recipe ${recipeId} not found`);
2889
- }
2890
- if (state.disabledRecipes?.includes(recipeId)) {
2891
- throw new Error(`Recipe ${recipeId} is disabled`);
2892
- }
2893
- if (recipe.inputs) {
2894
- for (const [entityId, required] of Object.entries(recipe.inputs)) {
2895
- const available = state.inventory[entityId] || 0;
2896
- if (available < required) {
2897
- throw new Error(
2898
- `Insufficient ${entityId}: required ${required}, available ${available}`
2899
- );
2900
- }
2901
- }
2902
- }
2903
- if (recipe.inputs) {
2904
- for (const [entityId, input] of Object.entries(recipe.inputs)) {
2905
- const inventoryValue = state.inventory[entityId] || 0;
2906
- if (typeof input === "number" && typeof inventoryValue === "number") {
2907
- state.inventory[entityId] = inventoryValue - input;
2908
- }
2909
- }
2910
- }
2911
- if (recipe.beginEffects) {
2912
- this.applyEffects(state, recipe.beginEffects);
2913
- }
2914
- const runId = this.generateRunId();
2915
- const now = Date.now();
2916
- const expiresAt = now + (recipe.duration || 0);
2917
- const run = {
2918
- id: runId,
2919
- recipeId,
2920
- status: "running",
2921
- startTime: now,
2922
- expiresAt,
2923
- inputs: recipe.inputs || {}
2924
- };
2925
- state.activeRuns.push(run);
2926
- if (recipe.duration === 0) {
2927
- this.completeRun(appIdentifier, runId);
2928
- return { status: "completed", runId };
2929
- } else {
2930
- const mockActiveTimers = this.mockActiveTimers;
2931
- const timer = setTimeout(() => {
2932
- this.completeRun(appIdentifier, runId);
2933
- }, recipe.duration);
2934
- const timers = mockActiveTimers.get(appIdentifier) || [];
2935
- timers.push(timer);
2936
- mockActiveTimers.set(appIdentifier, timers);
2937
- return {
2938
- status: "running",
2939
- runId,
2940
- expiresAt: new Date(expiresAt).toISOString()
2941
- };
2942
- }
2943
- }
2944
- async initializeSimulationState(appIdentifier) {
2945
- this.log(`Initializing simulation state for ${appIdentifier}`);
2946
- const providedSimulationConfig = this.providedSimulationConfig;
2947
- const mockSimulationConfigs = this.mockSimulationConfigs;
2948
- const mockSimulationStates = this.mockSimulationStates;
2949
- const mockActiveTimers = this.mockActiveTimers;
2950
- const config = providedSimulationConfig || {
2951
- version: "1.0",
2952
- entities: {},
2953
- recipes: {}
2954
- };
2955
- mockSimulationConfigs.set(appIdentifier, config);
2956
- const initialInventory = {};
2957
- if (providedSimulationConfig && config.entities) {
2958
- Object.keys(config.entities).forEach((entityId) => {
2959
- initialInventory[entityId] = 0;
2960
- });
2961
- }
2962
- const state = {
2963
- inventory: initialInventory,
2964
- activeRuns: [],
2965
- disabledRecipes: new Array()
2966
- };
2967
- if (config.recipes) {
2968
- Object.entries(config.recipes).forEach(([recipeId, recipe]) => {
2969
- if (recipe.metadata?.startsDisabled) {
2970
- state.disabledRecipes.push(recipeId);
2971
- }
2972
- });
2973
- }
2974
- mockSimulationStates.set(appIdentifier, state);
2975
- mockActiveTimers.set(appIdentifier, []);
2976
- console.log(
2977
- `[Venus Simulation Mock] Initialized state for ${appIdentifier}:`,
2978
- state
2979
- );
2980
- if (config.recipes) {
2981
- Object.entries(config.recipes).forEach(([recipeId, recipe]) => {
2982
- const isAutoRestart = recipe.autoRestart || recipe.metadata?.autoRestart;
2983
- if (isAutoRestart && recipe.outputs) {
2984
- this.log(`Found auto-restart recipe: ${recipeId}`, {
2985
- topLevelAutoRestart: recipe.autoRestart,
2986
- metadataAutoRestart: recipe.metadata?.autoRestart,
2987
- hasOutputs: !!recipe.outputs,
2988
- duration: recipe.duration
2989
- });
2990
- const condition = recipe.maxRestartCondition || recipe.metadata?.maxRestartCondition;
2991
- if (condition && condition.entity) {
2992
- const currentAmount = initialInventory[condition.entity] || 0;
2993
- if (currentAmount < condition.maxValue) {
2994
- console.log(
2995
- `[Venus Simulation Mock] Auto-starting ${recipeId} at initialization`,
2996
- {
2997
- currentAmount,
2998
- maxValue: condition.maxValue,
2999
- entity: condition.entity
3000
- }
3001
- );
3002
- setTimeout(() => {
3003
- this.executeRecipe(appIdentifier, recipeId, {});
3004
- }, 1e3);
3005
- }
3006
- } else {
3007
- console.log(
3008
- `[Venus Simulation Mock] Auto-starting ${recipeId} at initialization (no condition)`
3009
- );
3010
- setTimeout(() => {
3011
- this.executeRecipe(appIdentifier, recipeId, {});
3012
- }, 1e3);
3013
- }
3014
- }
3015
- });
3016
- }
3017
- return state;
3018
- }
3019
- generateRunId() {
3020
- return "run_" + Date.now() + "_" + Math.random().toString(36).substr(2, 9);
3021
- }
3022
- completeRun(appIdentifier, runId) {
3023
- this.log(`Completing run ${runId} for ${appIdentifier}`);
3024
- const mockSimulationConfigs = this.mockSimulationConfigs;
3025
- const mockSimulationStates = this.mockSimulationStates;
3026
- const config = mockSimulationConfigs.get(appIdentifier);
3027
- const state = mockSimulationStates.get(appIdentifier);
3028
- if (!config || !state) return;
3029
- const runIndex = state.activeRuns.findIndex((r) => r.id === runId);
3030
- if (runIndex === -1) return;
3031
- const run = state.activeRuns[runIndex];
3032
- const recipe = config.recipes?.[run.recipeId];
3033
- if (!recipe) return;
3034
- const outputs = {};
3035
- const rng = this.createSeededRandom(runId);
3036
- if (recipe.outputs) {
3037
- for (const [entityId, value] of Object.entries(recipe.outputs)) {
3038
- if (typeof value === "number") {
3039
- outputs[entityId] = value;
3040
- } else if (typeof value === "object" && value != null && "min" in value && "max" in value && typeof value.min == "number" && typeof value.max === "number") {
3041
- outputs[entityId] = Math.floor(rng() * (value.max - value.min + 1)) + value.min;
3042
- }
3059
+ roomId: options?.roomId || null,
3060
+ includeActorRecipes: options?.includeActorRecipes || false
3043
3061
  }
3044
- }
3045
- for (const [entityId, amount] of Object.entries(outputs)) {
3046
- state.inventory[entityId] = (state.inventory[entityId] || 0) + amount;
3047
- }
3048
- if (recipe.endEffects) {
3049
- this.applyEffects(state, recipe.endEffects);
3050
- }
3051
- run.status = "completed";
3052
- run.outputs = outputs;
3053
- state.activeRuns.splice(runIndex, 1);
3054
- const isAutoRestart = recipe.autoRestart || recipe.metadata?.autoRestart;
3055
- if (isAutoRestart) {
3056
- console.log(
3057
- `[Venus Simulation Mock] Checking auto-restart for ${run.recipeId}`,
3058
- {
3059
- topLevelAutoRestart: recipe.autoRestart,
3060
- metadataAutoRestart: recipe.metadata?.autoRestart,
3061
- hasCondition: !!(recipe.maxRestartCondition || recipe.metadata?.maxRestartCondition)
3062
- }
3063
- );
3064
- const condition = recipe.maxRestartCondition || recipe.metadata?.maxRestartCondition;
3065
- if (condition) {
3066
- const currentAmount = state.inventory[condition.entity] || 0;
3067
- if (currentAmount < condition.maxValue) {
3068
- console.log(
3069
- `[Venus Simulation Mock] Auto-restarting ${run.recipeId}`,
3070
- {
3071
- currentAmount,
3072
- maxValue: condition.maxValue,
3073
- entity: condition.entity
3074
- }
3075
- );
3076
- setTimeout(() => {
3077
- this.executeRecipe(appIdentifier, run.recipeId, recipe.inputs || {});
3078
- }, 1e3);
3079
- }
3080
- } else {
3081
- console.log(
3082
- `[Venus Simulation Mock] Auto-restarting ${run.recipeId} (no condition)`
3083
- );
3084
- setTimeout(() => {
3085
- this.executeRecipe(appIdentifier, run.recipeId, recipe.inputs || {});
3086
- }, 1e3);
3062
+ );
3063
+ }
3064
+ getRecipeRequirementsAsync(recipe) {
3065
+ return this.rpcClient.call(
3066
+ "H5_SIMULATION_GET_RECIPE_REQUIREMENTS" /* H5_SIMULATION_GET_RECIPE_REQUIREMENTS */,
3067
+ {
3068
+ recipeId: recipe.recipeId,
3069
+ entity: recipe.entity,
3070
+ batchAmount: recipe.batchAmount
3087
3071
  }
3088
- }
3089
- console.log(
3090
- `[Venus Simulation Mock] Completed run ${runId}, outputs:`,
3091
- outputs
3092
3072
  );
3093
3073
  }
3094
- createSeededRandom(seed) {
3095
- let hash = 0;
3096
- for (let i = 0; i < seed.length; i++) {
3097
- const char = seed.charCodeAt(i);
3098
- hash = (hash << 5) - hash + char;
3099
- hash = hash & hash;
3100
- }
3101
- return () => {
3102
- hash = (hash * 9301 + 49297) % 233280;
3103
- return hash / 233280;
3104
- };
3074
+ getBatchRecipeRequirementsAsync(recipes) {
3075
+ return this.rpcClient.call(
3076
+ "H5_SIMULATION_GET_BATCH_RECIPE_REQUIREMENTS" /* H5_SIMULATION_GET_BATCH_RECIPE_REQUIREMENTS */,
3077
+ {
3078
+ recipes
3079
+ }
3080
+ );
3105
3081
  }
3106
- applyEffects(state, effects) {
3107
- if (!effects || !Array.isArray(effects)) return;
3108
- for (const effect of effects) {
3109
- switch (effect.type) {
3110
- case "set":
3111
- state.inventory[effect.target] = effect.value;
3112
- console.log(
3113
- `[Venus Simulation Mock] Effect: Set ${effect.target} = ${effect.value}`
3114
- );
3115
- break;
3116
- case "add":
3117
- state.inventory[effect.target] = (state.inventory[effect.target] || 0) + effect.value;
3118
- console.log(
3119
- `[Venus Simulation Mock] Effect: Add ${effect.value} to ${effect.target} (new value: ${state.inventory[effect.target]})`
3120
- );
3121
- break;
3122
- case "multiply":
3123
- state.inventory[effect.target] = (state.inventory[effect.target] || 0) * effect.value;
3124
- console.log(
3125
- `[Venus Simulation Mock] Effect: Multiply ${effect.target} by ${effect.value} (new value: ${state.inventory[effect.target]})`
3126
- );
3127
- break;
3128
- case "min":
3129
- state.inventory[effect.target] = Math.max(
3130
- state.inventory[effect.target] || 0,
3131
- effect.value
3132
- );
3133
- console.log(
3134
- `[Venus Simulation Mock] Effect: Set ${effect.target} min ${effect.value} (new value: ${state.inventory[effect.target]})`
3135
- );
3136
- break;
3137
- case "max":
3138
- state.inventory[effect.target] = Math.min(
3139
- state.inventory[effect.target] || 0,
3140
- effect.value
3141
- );
3142
- console.log(
3143
- `[Venus Simulation Mock] Effect: Set ${effect.target} max ${effect.value} (new value: ${state.inventory[effect.target]})`
3144
- );
3145
- break;
3146
- case "enable_recipe":
3147
- if (state.disabledRecipes?.includes(effect.target)) {
3148
- state.disabledRecipes = state.disabledRecipes.filter(
3149
- (r) => r !== effect.target
3150
- );
3151
- console.log(
3152
- `[Venus Simulation Mock] Effect: Enabled recipe ${effect.target}`
3153
- );
3154
- }
3155
- break;
3156
- case "disable_recipe":
3157
- if (!state.disabledRecipes) state.disabledRecipes = [];
3158
- if (!state.disabledRecipes.includes(effect.target)) {
3159
- state.disabledRecipes.push(effect.target);
3160
- console.log(
3161
- `[Venus Simulation Mock] Effect: Disabled recipe ${effect.target}`
3162
- );
3163
- }
3164
- break;
3165
- case "trigger_recipe":
3166
- console.log(
3167
- `[Venus Simulation Mock] Effect: Trigger recipe ${effect.target} (not implemented)`
3168
- );
3169
- break;
3170
- default:
3171
- console.warn(
3172
- `[Venus Simulation Mock] Unknown effect type: ${effect.type}`
3173
- );
3082
+ triggerRecipeChainAsync(recipeId, options) {
3083
+ return this.rpcClient.call(
3084
+ "H5_SIMULATION_TRIGGER_RECIPE_CHAIN" /* H5_SIMULATION_TRIGGER_RECIPE_CHAIN */,
3085
+ {
3086
+ triggerRecipeId: recipeId,
3087
+ context: options?.context,
3088
+ roomId: options?.roomId
3174
3089
  }
3175
- }
3090
+ );
3176
3091
  }
3177
- async getConfigAsync() {
3178
- console.log("[Venus Simulation Mock] getConfigAsync called");
3179
- const appIdentifier = this.appId;
3180
- const mockSimulationConfigs = this.mockSimulationConfigs;
3181
- const config = mockSimulationConfigs.get(appIdentifier) || {
3182
- version: "1.0",
3183
- entities: {},
3184
- recipes: {}
3185
- };
3186
- return config;
3092
+ getEntityMetadataAsync(entityId) {
3093
+ return this.rpcClient.call(
3094
+ "H5_SIMULATION_GET_ENTITY_METADATA" /* H5_SIMULATION_GET_ENTITY_METADATA */,
3095
+ {
3096
+ entityId
3097
+ }
3098
+ );
3187
3099
  }
3188
- async getStateAsync(roomId) {
3189
- this.log("getStateAsync called:", roomId);
3190
- const appIdentifier = this.appId;
3191
- const mockSimulationStates = this.mockSimulationStates;
3192
- let state = mockSimulationStates.get(appIdentifier);
3193
- if (!state) {
3194
- state = await this.initializeSimulationState(appIdentifier);
3195
- }
3196
- const mockSimulationConfigs = this.mockSimulationConfigs;
3197
- return {
3198
- ...state,
3199
- roomId,
3200
- configuration: mockSimulationConfigs.get(appIdentifier)
3201
- };
3100
+ async resolveFieldValueAsync(entityId, fieldPath, entity) {
3101
+ const response = await this.rpcClient.call(
3102
+ "H5_SIMULATION_RESOLVE_VALUE" /* H5_SIMULATION_RESOLVE_VALUE */,
3103
+ {
3104
+ entityId,
3105
+ fieldPath,
3106
+ entity
3107
+ }
3108
+ );
3109
+ return response.value;
3202
3110
  }
3203
- async assignItemToSlotAsync(containerId, slotId, itemId) {
3204
- this.log("assignItemToSlotAsync called:", {
3205
- containerId,
3206
- slotId,
3207
- itemId
3208
- });
3209
- return { success: true, message: "Mock assignment successful" };
3111
+ handleSimulationUpdate(notification) {
3112
+ if (!notification || !notification.subscriptionId) {
3113
+ console.warn("[Venus SDK] Received malformed simulation update");
3114
+ return;
3115
+ }
3116
+ const callback = this.subscriptionCallbacks.get(notification.subscriptionId);
3117
+ if (!callback) {
3118
+ console.warn(
3119
+ "[Venus SDK] Received update for unknown subscription:",
3120
+ notification.subscriptionId
3121
+ );
3122
+ return;
3123
+ }
3124
+ try {
3125
+ callback(notification.updates);
3126
+ } catch (error) {
3127
+ console.error("[Venus SDK] Error in simulation subscription callback", error);
3128
+ }
3210
3129
  }
3211
- async removeItemFromSlotAsync(containerId, slotId) {
3212
- this.log("removeItemFromSlotAsync called:", {
3213
- containerId,
3214
- slotId
3215
- });
3216
- return { success: true, message: "Mock removal successful" };
3130
+ ensureValidSubscribeOptions(options) {
3131
+ if (typeof options !== "object" || options === null) {
3132
+ throw new Error("Simulation subscribe requires an options object");
3133
+ }
3134
+ const opts = options;
3135
+ if (typeof opts.onUpdate !== "function") {
3136
+ throw new Error("Simulation subscribe requires an onUpdate callback");
3137
+ }
3138
+ const hasFilter = Array.isArray(opts.entities) && opts.entities.length > 0 || Array.isArray(opts.tags) && opts.tags.length > 0 || Boolean(opts.activeRuns);
3139
+ if (!hasFilter) {
3140
+ throw new Error(
3141
+ "Simulation subscribe requires at least one filter (entities, tags, activeRuns)"
3142
+ );
3143
+ }
3217
3144
  }
3218
3145
  };
3219
3146
 
3220
3147
  // src/simulation/index.ts
3221
3148
  function initializeSimulation(venusApi, host) {
3222
- console.log("[Venus SDK] Initializing new Simulation Api");
3223
3149
  venusApi.simulation = {
3224
3150
  isEnabled: () => true
3225
3151
  };
3226
3152
  venusApi.simulation.getConfigAsync = () => {
3227
3153
  return host.simulation.getConfigAsync();
3228
3154
  };
3229
- venusApi.simulation.getStateAsync = (options) => {
3230
- return host.simulation.getStateAsync(options?.roomId);
3155
+ venusApi.simulation.getStateAsync = (roomId) => {
3156
+ return host.simulation.getStateAsync(roomId);
3231
3157
  };
3232
3158
  venusApi.simulation.executeRecipeAsync = (recipeId, inputs, options) => {
3233
3159
  return host.simulation.executeRecipeAsync(recipeId, inputs, options);
@@ -3238,31 +3164,17 @@ function initializeSimulation(venusApi, host) {
3238
3164
  venusApi.simulation.collectRecipeAsync = (runId) => {
3239
3165
  return host.simulation.collectRecipeAsync(runId);
3240
3166
  };
3241
- venusApi.simulation.executeScopedRecipeAsync = (recipeId, entity, inputs, roomId, options) => {
3242
- return host.simulation.executeScopedRecipeAsync(recipeId, entity, inputs, {
3243
- roomId,
3244
- ...options
3245
- });
3167
+ venusApi.simulation.executeScopedRecipeAsync = (recipeId, entity, inputs, options) => {
3168
+ return host.simulation.executeScopedRecipeAsync(recipeId, entity, inputs, options);
3246
3169
  };
3247
- venusApi.simulation.triggerRecipeChainAsync = (recipeId, context, roomId) => {
3248
- return host.simulation.triggerRecipeChainAsync(recipeId, {
3249
- context,
3250
- roomId
3251
- });
3170
+ venusApi.simulation.triggerRecipeChainAsync = (recipeId, options) => {
3171
+ return host.simulation.triggerRecipeChainAsync(recipeId, options);
3252
3172
  };
3253
- venusApi.simulation.getAvailableRecipesAsync = async (roomId, includeActorRecipes) => {
3254
- const result = await host.simulation.getAvailableRecipesAsync({
3255
- roomId,
3256
- includeActorRecipes
3257
- });
3258
- return result.recipes;
3173
+ venusApi.simulation.getAvailableRecipesAsync = async (options) => {
3174
+ return host.simulation.getAvailableRecipesAsync(options);
3259
3175
  };
3260
- venusApi.simulation.getRecipeRequirementsAsync = (recipeId, entity, amount) => {
3261
- return host.simulation.getRecipeRequirementsAsync({
3262
- recipeId,
3263
- entity,
3264
- batchAmount: amount
3265
- });
3176
+ venusApi.simulation.getRecipeRequirementsAsync = (recipe) => {
3177
+ return host.simulation.getRecipeRequirementsAsync(recipe);
3266
3178
  };
3267
3179
  venusApi.simulation.getBatchRecipeRequirementsAsync = (recipes) => {
3268
3180
  return host.simulation.getBatchRecipeRequirementsAsync(recipes);
@@ -3305,9 +3217,6 @@ function initializeSimulation(venusApi, host) {
3305
3217
  itemId
3306
3218
  );
3307
3219
  };
3308
- venusApi.simulation.sumContributions = (contributions) => {
3309
- return host.simulation.sumContributions(contributions);
3310
- };
3311
3220
  }
3312
3221
 
3313
3222
  // src/time/utils.ts
@@ -3326,9 +3235,11 @@ function isPacificDaylightTime(date) {
3326
3235
 
3327
3236
  // src/time/HostTimeApi.ts
3328
3237
  var HostTimeApi = class {
3329
- constructor(rpcClient) {
3238
+ constructor(rpcClient, venusApi) {
3330
3239
  __publicField(this, "rpcClient");
3240
+ __publicField(this, "venusApi");
3331
3241
  this.rpcClient = rpcClient;
3242
+ this.venusApi = venusApi;
3332
3243
  }
3333
3244
  async requestTimeAsync() {
3334
3245
  const response = await this.rpcClient.call(
@@ -3338,13 +3249,7 @@ var HostTimeApi = class {
3338
3249
  return response;
3339
3250
  }
3340
3251
  formatTime(timestamp, options) {
3341
- let locale = "en-US";
3342
- const windowVenus = window.venus;
3343
- if (windowVenus._config.locale) {
3344
- locale = windowVenus._config.locale;
3345
- } else if (windowVenus._config.environment && windowVenus._config.environment.browserInfo && windowVenus._config.environment.browserInfo.language) {
3346
- locale = windowVenus._config.environment.browserInfo.language;
3347
- }
3252
+ const locale = this.venusApi.getLocale();
3348
3253
  const date = new Date(timestamp);
3349
3254
  const dateTimeOptions = {
3350
3255
  dateStyle: options.dateStyle || "medium",
@@ -3356,13 +3261,7 @@ var HostTimeApi = class {
3356
3261
  }
3357
3262
  formatNumber(value, options) {
3358
3263
  try {
3359
- let locale = "en-US";
3360
- const windowVenus = window.venus;
3361
- if (windowVenus._config.locale) {
3362
- locale = windowVenus._config.locale;
3363
- } else if (windowVenus._config.environment && windowVenus._config.environment.browserInfo && windowVenus._config.environment.browserInfo.language) {
3364
- locale = windowVenus._config.environment.browserInfo.language;
3365
- }
3264
+ const locale = this.venusApi.getLocale();
3366
3265
  const numberOptions = {
3367
3266
  style: options?.style || "decimal",
3368
3267
  minimumFractionDigits: options?.minimumFractionDigits || 0,
@@ -3425,18 +3324,17 @@ var MockTimeApi = class {
3425
3324
  this.venusApi = venusApi;
3426
3325
  }
3427
3326
  formatNumber(value, options) {
3428
- const locale = this.getLocale();
3327
+ const locale = this.venusApi.getLocale();
3429
3328
  const numberOptions = {
3430
3329
  style: options?.style || "decimal",
3431
3330
  minimumFractionDigits: options?.minimumFractionDigits || 0,
3432
3331
  maximumFractionDigits: options?.maximumFractionDigits || 2,
3433
3332
  ...options
3434
3333
  };
3435
- console.log(`[Venus Mock] Formatting number ${value} with locale ${locale}`);
3436
3334
  return value.toLocaleString(locale, numberOptions);
3437
3335
  }
3438
3336
  formatTime(timestamp, options) {
3439
- const locale = this.getLocale();
3337
+ const locale = this.venusApi.getLocale();
3440
3338
  const date = new Date(timestamp);
3441
3339
  const dateTimeOptions = {
3442
3340
  dateStyle: options.dateStyle || "medium",
@@ -3444,13 +3342,9 @@ var MockTimeApi = class {
3444
3342
  hour12: options.hour12 !== void 0 ? options.hour12 : true,
3445
3343
  ...options
3446
3344
  };
3447
- console.log(
3448
- `[Venus Mock] Formatting time ${timestamp} with locale ${locale}`
3449
- );
3450
3345
  return date.toLocaleString(locale, dateTimeOptions);
3451
3346
  }
3452
3347
  async getFutureTimeAsync(options) {
3453
- console.log("[Venus Mock] Getting future time with options:", options);
3454
3348
  const timeInfo = await this.requestTimeAsync();
3455
3349
  const serverTime = new Date(timeInfo.serverTime);
3456
3350
  const result = new Date(serverTime);
@@ -3495,7 +3389,6 @@ var MockTimeApi = class {
3495
3389
  return result.getTime();
3496
3390
  }
3497
3391
  async requestTimeAsync() {
3498
- console.log("[Venus Mock] Requesting time");
3499
3392
  await createMockDelay(MOCK_DELAYS.short);
3500
3393
  const venusApi = this.venusApi;
3501
3394
  const mockOffset = venusApi._mock.serverTimeOffset || 2500;
@@ -3509,23 +3402,8 @@ var MockTimeApi = class {
3509
3402
  formattedTime: new Date(localTime).toISOString(),
3510
3403
  locale: venusApi._mock.user?.locale || "en-US"
3511
3404
  };
3512
- console.log("[Venus Mock] Time response:", {
3513
- serverTime: new Date(timeInfo.serverTime).toISOString(),
3514
- localTime: new Date(timeInfo.localTime).toISOString(),
3515
- timezoneOffset: timeInfo.timezoneOffset
3516
- });
3517
3405
  return timeInfo;
3518
3406
  }
3519
- getLocale() {
3520
- const venusApi = this.venusApi;
3521
- let locale = "en-US";
3522
- if (venusApi._mock.user && venusApi._mock.user.locale) {
3523
- locale = venusApi._mock.user.locale;
3524
- } else if (venusApi._mock.environment && venusApi._mock.environment.browserInfo.language) {
3525
- locale = venusApi._mock.environment.browserInfo.language;
3526
- }
3527
- return locale;
3528
- }
3529
3407
  };
3530
3408
 
3531
3409
  // src/time/index.ts
@@ -3545,11 +3423,176 @@ function initializeTime(venusApi, host) {
3545
3423
  }
3546
3424
 
3547
3425
  // src/version.ts
3548
- var SDK_VERSION = "3.0.4";
3426
+ var SDK_VERSION = "3.2.0";
3427
+
3428
+ // src/shared-assets/embeddedLibrariesManifest.ts
3429
+ var DEFAULT_SHARED_LIB_CDN_BASE = "https://venus-static-01293ak.web.app/libs";
3430
+ var EMBEDDED_LIBRARIES = [
3431
+ {
3432
+ libraryKey: "phaser@3.90.0",
3433
+ assetKey: "library:phaser@3.90.0",
3434
+ packageName: "phaser",
3435
+ version: "3.90.0",
3436
+ globalVar: "Phaser",
3437
+ cdnPath: "phaser/3.90.0/phaser.min.js",
3438
+ moduleSpecifiers: [{ match: "exact", value: "phaser" }],
3439
+ loadStage: 0,
3440
+ enabled: true
3441
+ },
3442
+ {
3443
+ libraryKey: "react@18.3.1",
3444
+ assetKey: "library:react@18.3.1",
3445
+ packageName: "react",
3446
+ version: "18.3.1",
3447
+ globalVar: "React",
3448
+ cdnPath: "react/18.3.1/react.production.min.js",
3449
+ moduleSpecifiers: [
3450
+ { match: "exact", value: "react", behavior: "namespace" },
3451
+ { match: "exact", value: "react/jsx-runtime", behavior: "react-jsx-runtime" },
3452
+ {
3453
+ match: "exact",
3454
+ value: "react/jsx-dev-runtime",
3455
+ behavior: "react-jsx-dev-runtime"
3456
+ }
3457
+ ],
3458
+ loadStage: 0,
3459
+ // Must load before ReactDOM
3460
+ enabled: true
3461
+ },
3462
+ {
3463
+ libraryKey: "react-dom@18.3.1",
3464
+ assetKey: "library:react-dom@18.3.1",
3465
+ packageName: "react-dom",
3466
+ version: "18.3.1",
3467
+ globalVar: "ReactDOM",
3468
+ cdnPath: "react-dom/18.3.1/react-dom.production.min.js",
3469
+ moduleSpecifiers: [
3470
+ { match: "exact", value: "react-dom", behavior: "namespace" },
3471
+ { match: "exact", value: "react-dom/client", behavior: "namespace" }
3472
+ ],
3473
+ loadStage: 1,
3474
+ // Depends on React (stage 0)
3475
+ enabled: true
3476
+ },
3477
+ {
3478
+ libraryKey: "three@0.170.0",
3479
+ assetKey: "library:three@0.170.0",
3480
+ packageName: "three",
3481
+ version: "0.170.0",
3482
+ globalVar: "THREE",
3483
+ cdnPath: "three/r170/three.min.js",
3484
+ moduleSpecifiers: [
3485
+ { match: "exact", value: "three", behavior: "namespace" },
3486
+ { match: "prefix", value: "three/examples/jsm/", behavior: "namespace" }
3487
+ ],
3488
+ loadStage: 0,
3489
+ enabled: true
3490
+ },
3491
+ {
3492
+ libraryKey: "matter-js@0.19.0",
3493
+ assetKey: "library:matter-js@0.19.0",
3494
+ packageName: "matter-js",
3495
+ version: "0.19.0",
3496
+ globalVar: "Matter",
3497
+ cdnPath: "matter-js/0.19.0/matter.min.js",
3498
+ moduleSpecifiers: [{ match: "exact", value: "matter-js" }],
3499
+ loadStage: 0,
3500
+ enabled: true
3501
+ },
3502
+ {
3503
+ libraryKey: "inkjs@2.2.0",
3504
+ assetKey: "library:inkjs@2.2.0",
3505
+ packageName: "inkjs",
3506
+ version: "2.2.0",
3507
+ globalVar: "inkjs",
3508
+ cdnPath: "inkjs/2.2.0/ink.min.js",
3509
+ moduleSpecifiers: [{ match: "exact", value: "inkjs" }],
3510
+ loadStage: 0,
3511
+ enabled: true
3512
+ },
3513
+ {
3514
+ libraryKey: "zustand@5.0.3",
3515
+ assetKey: "library:zustand@5.0.3",
3516
+ packageName: "zustand",
3517
+ version: "5.0.3",
3518
+ globalVar: "zustand",
3519
+ cdnPath: "zustand/5.0.3/zustand.min.js",
3520
+ moduleSpecifiers: [
3521
+ { match: "exact", value: "zustand" },
3522
+ { match: "exact", value: "zustand/middleware" }
3523
+ ],
3524
+ loadStage: 0,
3525
+ enabled: true
3526
+ },
3527
+ {
3528
+ libraryKey: "ammo.js@2024.11",
3529
+ assetKey: "library:ammo.js@2024.11",
3530
+ packageName: "ammo.js",
3531
+ version: "2024.11",
3532
+ globalVar: "Ammo",
3533
+ cdnPath: "ammo/2024.11/ammo.js",
3534
+ moduleSpecifiers: [
3535
+ { match: "exact", value: "ammo.js" },
3536
+ { match: "exact", value: "ammo.js/builds/ammo.wasm.js" }
3537
+ ],
3538
+ loadStage: 0,
3539
+ enabled: false
3540
+ // Not ready yet - WASM loading needs additional work
3541
+ }
3542
+ ];
3543
+ var EMBEDDED_LIBRARY_BY_KEY = EMBEDDED_LIBRARIES.reduce(
3544
+ (acc, lib) => {
3545
+ acc[lib.libraryKey] = lib;
3546
+ return acc;
3547
+ },
3548
+ {}
3549
+ );
3550
+ var MODULE_TO_LIBRARY_SPECIFIERS = EMBEDDED_LIBRARIES.filter(
3551
+ (lib) => lib.enabled
3552
+ ).flatMap(
3553
+ (lib) => lib.moduleSpecifiers.map((specifier) => ({
3554
+ ...specifier,
3555
+ libraryKey: lib.libraryKey
3556
+ }))
3557
+ );
3558
+ function getLibraryDefinition(libraryKey) {
3559
+ const definition = EMBEDDED_LIBRARY_BY_KEY[libraryKey];
3560
+ if (!definition) {
3561
+ const availableKeys = Object.keys(EMBEDDED_LIBRARY_BY_KEY).join(", ");
3562
+ throw new Error(
3563
+ `Unsupported embedded library: ${libraryKey}. Available libraries: ${availableKeys}`
3564
+ );
3565
+ }
3566
+ return definition;
3567
+ }
3549
3568
 
3550
- // src/shared-assets/consts.ts
3551
- var BurgerTimeAssetsCdnPath = "burger-time/Core.stow";
3552
- var CharacterAssetsCdnPath = "burger-time/Character.stow";
3569
+ // src/shared-assets/base64Utils.ts
3570
+ function base64ToArrayBuffer(base64) {
3571
+ const binaryString = atob(base64);
3572
+ const len = binaryString.length;
3573
+ const bytes = new Uint8Array(len);
3574
+ for (let i = 0; i < len; i++) {
3575
+ bytes[i] = binaryString.charCodeAt(i);
3576
+ }
3577
+ return bytes.buffer;
3578
+ }
3579
+ function base64ToUtf8(base64) {
3580
+ if (typeof TextDecoder !== "undefined") {
3581
+ const decoder = new TextDecoder("utf-8");
3582
+ const buffer = base64ToArrayBuffer(base64);
3583
+ return decoder.decode(new Uint8Array(buffer));
3584
+ }
3585
+ if (typeof globalThis !== "undefined" && typeof globalThis.Buffer !== "undefined") {
3586
+ const BufferCtor = globalThis.Buffer;
3587
+ return BufferCtor.from(base64, "base64").toString("utf-8");
3588
+ }
3589
+ const binaryString = atob(base64);
3590
+ let result = "";
3591
+ for (let i = 0; i < binaryString.length; i++) {
3592
+ result += String.fromCharCode(binaryString.charCodeAt(i));
3593
+ }
3594
+ return decodeURIComponent(escape(result));
3595
+ }
3553
3596
 
3554
3597
  // src/shared-assets/RpcSharedAssetsApi.ts
3555
3598
  var RpcSharedAssetsApi = class {
@@ -3559,46 +3602,48 @@ var RpcSharedAssetsApi = class {
3559
3602
  this.rpcClient = rpcClient;
3560
3603
  this.venusApi = venusApi;
3561
3604
  }
3562
- async loadBurgerTimeAssetsBundle() {
3605
+ async loadAssetsBundle(game, bundleKey, fileType = "stow") {
3563
3606
  try {
3564
3607
  const response = await this.rpcClient.callT("H5_LOAD_EMBEDDED_ASSET" /* H5_LOAD_EMBEDDED_ASSET */, {
3565
- assetKey: "burgerTimeCoreBundle"
3608
+ assetKey: bundleKey
3566
3609
  });
3567
3610
  return base64ToArrayBuffer(response.base64Data);
3568
3611
  } catch (err) {
3569
3612
  try {
3570
- const blob = await this.venusApi.cdn.fetchBlob(BurgerTimeAssetsCdnPath);
3613
+ const blob = await this.venusApi.cdn.fetchBlob(`${game}/${bundleKey}.${fileType}`);
3571
3614
  return await blob.arrayBuffer();
3572
3615
  } catch (e) {
3573
- throw new Error("Failed to load burgerTimeAssetsBundle");
3616
+ throw new Error(`Failed to load ${bundleKey}`);
3574
3617
  }
3575
3618
  }
3576
3619
  }
3577
- async loadCharactersBundle() {
3620
+ async loadLibraryCode(libraryKey) {
3621
+ const definition = getLibraryDefinition(libraryKey);
3578
3622
  try {
3579
3623
  const response = await this.rpcClient.callT("H5_LOAD_EMBEDDED_ASSET" /* H5_LOAD_EMBEDDED_ASSET */, {
3580
- assetKey: "characters"
3624
+ assetKey: definition.assetKey
3581
3625
  });
3582
- return base64ToArrayBuffer(response.base64Data);
3626
+ return base64ToUtf8(response.base64Data);
3583
3627
  } catch (err) {
3628
+ console.error(
3629
+ `[Venus Libraries] Failed to load ${libraryKey} from host via RPC:`,
3630
+ err
3631
+ );
3632
+ console.warn(
3633
+ `[Venus Libraries] Falling back to CDN for ${libraryKey}. This may indicate an asset packaging issue.`
3634
+ );
3584
3635
  try {
3585
- const blob = await this.venusApi.cdn.fetchBlob(CharacterAssetsCdnPath);
3586
- return await blob.arrayBuffer();
3587
- } catch (e) {
3588
- throw new Error("Failed to load charactersBundle");
3636
+ const cdnUrl = this.venusApi.cdn.resolveSharedLibUrl(definition.cdnPath);
3637
+ const response = await this.venusApi.cdn.fetchFromCdn(cdnUrl);
3638
+ return await response.text();
3639
+ } catch (cdnError) {
3640
+ throw new Error(
3641
+ `Failed to load embedded library ${libraryKey}: RPC failed, CDN fallback failed: ${cdnError.message}`
3642
+ );
3589
3643
  }
3590
3644
  }
3591
3645
  }
3592
3646
  };
3593
- function base64ToArrayBuffer(base64) {
3594
- const binaryString = atob(base64);
3595
- const len = binaryString.length;
3596
- const bytes = new Uint8Array(len);
3597
- for (let i = 0; i < len; i++) {
3598
- bytes[i] = binaryString.charCodeAt(i);
3599
- }
3600
- return bytes.buffer;
3601
- }
3602
3647
 
3603
3648
  // src/shared-assets/MockSharedAssetsApi.ts
3604
3649
  var MockSharedAssetsApi = class {
@@ -3606,57 +3651,118 @@ var MockSharedAssetsApi = class {
3606
3651
  __publicField(this, "venusApi");
3607
3652
  this.venusApi = venusApi;
3608
3653
  }
3609
- async loadBurgerTimeAssetsBundle() {
3610
- const blob = await this.venusApi.cdn.fetchBlob(BurgerTimeAssetsCdnPath);
3654
+ async loadAssetsBundle(game, bundleKey, fileType = "stow") {
3655
+ const blob = await this.venusApi.cdn.fetchBlob(`${game}/${bundleKey}.${fileType}`);
3611
3656
  return await blob.arrayBuffer();
3612
3657
  }
3613
- async loadCharactersBundle() {
3614
- const blob = await this.venusApi.cdn.fetchBlob(CharacterAssetsCdnPath);
3615
- return await blob.arrayBuffer();
3658
+ async loadLibraryCode(libraryKey) {
3659
+ const definition = getLibraryDefinition(libraryKey);
3660
+ const url = this.venusApi.cdn.resolveSharedLibUrl(definition.cdnPath);
3661
+ const response = await this.venusApi.cdn.fetchFromCdn(url);
3662
+ return await response.text();
3616
3663
  }
3617
3664
  };
3618
3665
 
3666
+ // src/leaderboard/utils.ts
3667
+ var HASH_ALGORITHM_WEB_CRYPTO = "SHA-256";
3668
+ var HASH_ALGORITHM_NODE = "sha256";
3669
+ async function computeScoreHash(score, duration, token, sealingNonce, sealingSecret) {
3670
+ const payload = `score:${score}|duration:${duration}|token:${token}`;
3671
+ const fullPayload = `${payload}|nonce:${sealingNonce}`;
3672
+ const encoder = new TextEncoder();
3673
+ const keyData = encoder.encode(sealingSecret);
3674
+ const messageData = encoder.encode(fullPayload);
3675
+ const cryptoKey = await crypto.subtle.importKey(
3676
+ "raw",
3677
+ keyData,
3678
+ { name: "HMAC", hash: HASH_ALGORITHM_WEB_CRYPTO },
3679
+ false,
3680
+ ["sign"]
3681
+ );
3682
+ const signature = await crypto.subtle.sign("HMAC", cryptoKey, messageData);
3683
+ return Array.from(new Uint8Array(signature)).map((b) => b.toString(16).padStart(2, "0")).join("");
3684
+ }
3685
+
3619
3686
  // src/leaderboard/RpcLeaderboardApi.ts
3620
3687
  var RpcLeaderboardApi = class {
3621
3688
  constructor(rpcClient) {
3622
3689
  __publicField(this, "rpcClient");
3690
+ /** Cache of score tokens for automatic hash computation */
3691
+ __publicField(this, "tokenCache", /* @__PURE__ */ new Map());
3623
3692
  this.rpcClient = rpcClient;
3624
3693
  }
3625
- startRun(mode) {
3626
- return this.rpcClient.call(
3627
- "H5_LEADERBOARD_START_RUN" /* H5_LEADERBOARD_START_RUN */,
3694
+ /**
3695
+ * Create a score token for submitting a score.
3696
+ * Token is cached for automatic hash computation if score sealing is enabled.
3697
+ *
3698
+ * @param mode - Optional game mode
3699
+ * @returns Score token with sealing data if enabled
3700
+ */
3701
+ async createScoreToken(mode) {
3702
+ const token = await this.rpcClient.call(
3703
+ "H5_LEADERBOARD_CREATE_SCORE_TOKEN" /* H5_LEADERBOARD_CREATE_SCORE_TOKEN */,
3628
3704
  mode ? { mode } : {}
3629
3705
  );
3706
+ this.tokenCache.set(token.token, token);
3707
+ return token;
3630
3708
  }
3631
- submitScore(sessionId, score, durationSec, options) {
3709
+ /**
3710
+ * Submit a score to the leaderboard.
3711
+ * Automatically computes hash if score sealing is enabled and token was created via createScoreToken().
3712
+ *
3713
+ * @param params - Score submission parameters
3714
+ * @returns Submission result with acceptance status and rank
3715
+ * @throws Error if token not found in cache
3716
+ */
3717
+ async submitScore(params) {
3718
+ let hash;
3719
+ if (params.token) {
3720
+ const cachedToken = this.tokenCache.get(params.token);
3721
+ if (!cachedToken) {
3722
+ throw new Error(
3723
+ "Invalid token: not found in cache. Did you call createScoreToken() first?"
3724
+ );
3725
+ }
3726
+ if (cachedToken.sealingNonce && cachedToken.sealingSecret) {
3727
+ hash = await computeScoreHash(
3728
+ params.score,
3729
+ params.duration,
3730
+ params.token,
3731
+ cachedToken.sealingNonce,
3732
+ cachedToken.sealingSecret
3733
+ );
3734
+ }
3735
+ this.tokenCache.delete(params.token);
3736
+ }
3632
3737
  return this.rpcClient.call(
3633
3738
  "H5_LEADERBOARD_SUBMIT_SCORE" /* H5_LEADERBOARD_SUBMIT_SCORE */,
3634
3739
  {
3635
- sessionId,
3636
- score,
3637
- durationSec,
3638
- mode: options?.mode,
3639
- telemetry: options?.telemetry,
3640
- metadata: options?.metadata,
3641
- hash: options?.hash
3740
+ token: params.token,
3741
+ score: params.score,
3742
+ duration: params.duration,
3743
+ mode: params.mode,
3744
+ telemetry: params.telemetry,
3745
+ metadata: params.metadata,
3746
+ hash
3747
+ // undefined if no sealing, computed if sealing enabled
3642
3748
  }
3643
3749
  );
3644
3750
  }
3645
- getLeaderboard(options) {
3751
+ getPagedScores(options) {
3646
3752
  return this.rpcClient.call(
3647
- "H5_LEADERBOARD_GET" /* H5_LEADERBOARD_GET */,
3753
+ "H5_LEADERBOARD_GET_PAGED_SCORES" /* H5_LEADERBOARD_GET_PAGED_SCORES */,
3648
3754
  options ?? {}
3649
3755
  );
3650
3756
  }
3651
- getPlayerStats(options) {
3757
+ getMyRank(options) {
3652
3758
  return this.rpcClient.call(
3653
- "H5_LEADERBOARD_GET_PLAYER_STATS" /* H5_LEADERBOARD_GET_PLAYER_STATS */,
3759
+ "H5_LEADERBOARD_GET_MY_RANK" /* H5_LEADERBOARD_GET_MY_RANK */,
3654
3760
  options ?? {}
3655
3761
  );
3656
3762
  }
3657
- getLeaderboardHighlight(options) {
3763
+ getPodiumScores(options) {
3658
3764
  return this.rpcClient.call(
3659
- "H5_LEADERBOARD_GET_HIGHLIGHT" /* H5_LEADERBOARD_GET_HIGHLIGHT */,
3765
+ "H5_LEADERBOARD_GET_PODIUM_SCORES" /* H5_LEADERBOARD_GET_PODIUM_SCORES */,
3660
3766
  options ?? {}
3661
3767
  );
3662
3768
  }
@@ -3665,17 +3771,31 @@ var RpcLeaderboardApi = class {
3665
3771
  // src/leaderboard/MockLeaderboardApi.ts
3666
3772
  var MockLeaderboardApi = class {
3667
3773
  constructor(options) {
3668
- __publicField(this, "sessions", /* @__PURE__ */ new Map());
3774
+ __publicField(this, "tokens", /* @__PURE__ */ new Map());
3775
+ /** Cache of score tokens for automatic hash computation */
3776
+ __publicField(this, "tokenCache", /* @__PURE__ */ new Map());
3669
3777
  __publicField(this, "entriesByMode", /* @__PURE__ */ new Map());
3670
- __publicField(this, "sessionCounter", 0);
3671
- __publicField(this, "requiresHash", false);
3672
- if (options?.requiresHash) {
3673
- this.requiresHash = true;
3778
+ __publicField(this, "tokenCounter", 0);
3779
+ __publicField(this, "enableScoreSealing", false);
3780
+ __publicField(this, "scoreSealingSecret", "mock-leaderboard-secret-key");
3781
+ if (options?.enableScoreSealing) {
3782
+ this.enableScoreSealing = true;
3783
+ }
3784
+ if (options?.scoreSealingSecret) {
3785
+ this.scoreSealingSecret = options.scoreSealingSecret;
3674
3786
  }
3675
3787
  }
3788
+ /**
3789
+ * Configure mock leaderboard settings
3790
+ *
3791
+ * @param options - Configuration options
3792
+ */
3676
3793
  configure(options) {
3677
- if (typeof options.requiresHash === "boolean") {
3678
- this.requiresHash = options.requiresHash;
3794
+ if (typeof options.enableScoreSealing === "boolean") {
3795
+ this.enableScoreSealing = options.enableScoreSealing;
3796
+ }
3797
+ if (options.scoreSealingSecret) {
3798
+ this.scoreSealingSecret = options.scoreSealingSecret;
3679
3799
  }
3680
3800
  }
3681
3801
  generateNonce() {
@@ -3692,83 +3812,149 @@ var MockLeaderboardApi = class {
3692
3812
  }
3693
3813
  return this.entriesByMode.get(key);
3694
3814
  }
3695
- async startRun(mode) {
3696
- const sessionId = `mock_session_${++this.sessionCounter}`;
3815
+ /**
3816
+ * Create a mock score token for testing.
3817
+ * Token is cached for automatic hash computation if score sealing is enabled.
3818
+ *
3819
+ * @param mode - Optional game mode
3820
+ * @returns Score token with sealing data if enabled
3821
+ */
3822
+ async createScoreToken(mode) {
3823
+ const token = `mock_token_${++this.tokenCounter}`;
3697
3824
  const startTime = Date.now();
3698
3825
  const expiresAt = startTime + 36e5;
3699
3826
  const resolvedMode = mode || "default";
3700
- const hashNonce = this.requiresHash ? this.generateNonce() : null;
3701
- this.sessions.set(sessionId, {
3702
- id: sessionId,
3827
+ const sealingNonce = this.enableScoreSealing ? this.generateNonce() : null;
3828
+ const sealingSecret = this.enableScoreSealing ? this.scoreSealingSecret : null;
3829
+ this.tokens.set(token, {
3830
+ id: token,
3703
3831
  expiresAt,
3704
3832
  mode: resolvedMode,
3705
- hashNonce,
3833
+ sealingNonce,
3706
3834
  used: false
3707
3835
  });
3708
- return {
3709
- sessionId,
3836
+ const result = {
3837
+ token,
3710
3838
  startTime,
3711
3839
  expiresAt,
3712
- hashNonce,
3840
+ sealingNonce,
3841
+ sealingSecret,
3713
3842
  mode: resolvedMode
3714
3843
  };
3844
+ this.tokenCache.set(token, result);
3845
+ return result;
3715
3846
  }
3716
- async submitScore(sessionId, score, durationSec, options) {
3717
- const session = this.sessions.get(sessionId);
3718
- if (!session) {
3719
- throw new Error("Invalid leaderboard session");
3847
+ /**
3848
+ * Submit a mock score to the leaderboard.
3849
+ * Automatically computes hash if score sealing is enabled and token was created via createScoreToken().
3850
+ *
3851
+ * @param params - Score submission parameters
3852
+ * @returns Submission result with acceptance status and rank
3853
+ * @throws Error if token not found in cache or validation fails
3854
+ */
3855
+ async submitScore(params) {
3856
+ let hash;
3857
+ if (params.token) {
3858
+ const cachedToken = this.tokenCache.get(params.token);
3859
+ if (!cachedToken) {
3860
+ throw new Error(
3861
+ "Invalid token: not found in cache. Did you call createScoreToken() first?"
3862
+ );
3863
+ }
3864
+ if (cachedToken.sealingNonce && cachedToken.sealingSecret) {
3865
+ hash = await computeScoreHash(
3866
+ params.score,
3867
+ params.duration,
3868
+ params.token,
3869
+ cachedToken.sealingNonce,
3870
+ cachedToken.sealingSecret
3871
+ );
3872
+ }
3873
+ }
3874
+ if (!params.token) {
3875
+ const mode = params.mode || "default";
3876
+ const submittedAt2 = Date.now();
3877
+ const entry2 = {
3878
+ profileId: `mock_profile`,
3879
+ username: "Mock Player",
3880
+ avatarUrl: null,
3881
+ score: params.score,
3882
+ duration: params.duration,
3883
+ submittedAt: submittedAt2,
3884
+ token: "simple-mode",
3885
+ rank: null,
3886
+ zScore: null,
3887
+ isAnomaly: false,
3888
+ trustScore: 50,
3889
+ metadata: params.metadata ?? null,
3890
+ isSeed: false
3891
+ };
3892
+ const modeEntries2 = this.getEntriesForMode(mode);
3893
+ modeEntries2.push(entry2);
3894
+ modeEntries2.sort((a, b) => {
3895
+ if (b.score !== a.score) return b.score - a.score;
3896
+ return a.submittedAt - b.submittedAt;
3897
+ });
3898
+ modeEntries2.forEach((e, index) => {
3899
+ modeEntries2[index] = { ...e, rank: index + 1 };
3900
+ });
3901
+ const inserted2 = modeEntries2.find((e) => e.submittedAt === submittedAt2);
3902
+ return {
3903
+ accepted: true,
3904
+ rank: inserted2?.rank ?? null
3905
+ };
3906
+ }
3907
+ const scoreToken = this.tokens.get(params.token);
3908
+ if (!scoreToken) {
3909
+ throw new Error("Invalid score token");
3720
3910
  }
3721
- if (session.expiresAt < Date.now()) {
3722
- throw new Error("Invalid or expired leaderboard session");
3911
+ if (scoreToken.expiresAt < Date.now()) {
3912
+ throw new Error("Invalid or expired score token");
3723
3913
  }
3724
- if (session.used) {
3725
- throw new Error("Leaderboard session already used");
3914
+ if (scoreToken.used) {
3915
+ throw new Error("Score token already used");
3726
3916
  }
3727
- if (options?.mode && options.mode !== session.mode) {
3728
- throw new Error("Submission mode does not match session mode");
3917
+ if (params.mode && params.mode !== scoreToken.mode) {
3918
+ throw new Error("Submission mode does not match token mode");
3729
3919
  }
3730
- if (session.hashNonce && !options?.hash) {
3731
- throw new Error("Score hash is required for sealed leaderboard submissions");
3920
+ if (scoreToken.sealingNonce && !hash) {
3921
+ throw new Error("Score hash required when score sealing is enabled");
3732
3922
  }
3733
3923
  const submittedAt = Date.now();
3734
3924
  const entry = {
3735
3925
  profileId: `mock_profile`,
3736
3926
  username: "Mock Player",
3737
3927
  avatarUrl: null,
3738
- score,
3739
- durationSec,
3928
+ score: params.score,
3929
+ duration: params.duration,
3740
3930
  submittedAt,
3741
- sessionId,
3931
+ token: params.token,
3742
3932
  rank: null,
3743
3933
  zScore: null,
3744
3934
  isAnomaly: false,
3745
3935
  trustScore: 50,
3746
- metadata: options?.metadata ?? null,
3936
+ metadata: params.metadata ?? null,
3747
3937
  isSeed: false
3748
3938
  };
3749
- const modeEntries = this.getEntriesForMode(session.mode);
3939
+ const modeEntries = this.getEntriesForMode(scoreToken.mode);
3750
3940
  modeEntries.push(entry);
3751
3941
  modeEntries.sort((a, b) => {
3752
- if (b.score !== a.score) {
3753
- return b.score - a.score;
3754
- }
3942
+ if (b.score !== a.score) return b.score - a.score;
3755
3943
  return a.submittedAt - b.submittedAt;
3756
3944
  });
3757
3945
  modeEntries.forEach((e, index) => {
3758
- modeEntries[index] = {
3759
- ...e,
3760
- rank: index + 1
3761
- };
3946
+ modeEntries[index] = { ...e, rank: index + 1 };
3762
3947
  });
3763
- session.used = true;
3764
- session.hashNonce = null;
3765
- const inserted = modeEntries.find((e) => e.sessionId === sessionId && e.submittedAt === submittedAt);
3948
+ scoreToken.used = true;
3949
+ scoreToken.sealingNonce = null;
3950
+ this.tokenCache.delete(params.token);
3951
+ const inserted = modeEntries.find((e) => e.token === params.token && e.submittedAt === submittedAt);
3766
3952
  return {
3767
3953
  accepted: true,
3768
3954
  rank: inserted?.rank ?? null
3769
3955
  };
3770
3956
  }
3771
- async getLeaderboard(options) {
3957
+ async getPagedScores(options) {
3772
3958
  const limit = options?.limit ?? 10;
3773
3959
  const mode = options?.mode ?? "default";
3774
3960
  const modeEntries = [...this.getEntriesForMode(mode)];
@@ -3784,7 +3970,7 @@ var MockLeaderboardApi = class {
3784
3970
  periodInstance: options?.period ?? "alltime"
3785
3971
  };
3786
3972
  }
3787
- async getPlayerStats(_options) {
3973
+ async getMyRank(_options) {
3788
3974
  const mode = _options?.mode ?? "default";
3789
3975
  const modeEntries = this.getEntriesForMode(mode);
3790
3976
  const playerEntry = modeEntries[0] ?? null;
@@ -3797,7 +3983,7 @@ var MockLeaderboardApi = class {
3797
3983
  periodInstance: _options?.period ?? "alltime"
3798
3984
  };
3799
3985
  }
3800
- async getLeaderboardHighlight(options) {
3986
+ async getPodiumScores(options) {
3801
3987
  const mode = options?.mode ?? "default";
3802
3988
  const modeEntries = [...this.getEntriesForMode(mode)];
3803
3989
  const topCount = Math.max(1, Math.min(options?.topCount ?? 3, 10));
@@ -3865,117 +4051,28 @@ var MockPreloaderApi = class {
3865
4051
  };
3866
4052
 
3867
4053
  // src/game-preloader/RpcPreloaderApi.ts
3868
- var RpcPreloaderApi = class {
3869
- constructor(rpcClient) {
3870
- __publicField(this, "rpcClient");
3871
- this.rpcClient = rpcClient;
3872
- }
3873
- async showLoadScreen() {
3874
- await this.rpcClient.call("H5_SHOW_LOAD_SCREEN" /* H5_SHOW_LOAD_SCREEN */);
3875
- }
3876
- async hideLoadScreen() {
3877
- await this.rpcClient.call("H5_HIDE_LOAD_SCREEN" /* H5_HIDE_LOAD_SCREEN */);
3878
- }
3879
- async setLoaderText(text) {
3880
- await this.rpcClient.call("H5_SET_LOADER_TEXT" /* H5_SET_LOADER_TEXT */, { text });
3881
- }
3882
- async setLoaderProgress(progress) {
3883
- await this.rpcClient.call("H5_SET_LOADER_PROGRESS" /* H5_SET_LOADER_PROGRESS */, { progress });
3884
- }
3885
- };
3886
-
3887
- // src/game-preloader/index.ts
3888
- function initializePreloader(venusApi, host) {
3889
- venusApi.preloader = host.preloader;
3890
- }
3891
-
3892
- // src/post/MockPostApi.ts
3893
- var MockPostApi = class {
3894
- constructor(venusApi) {
3895
- __publicField(this, "venusApi");
3896
- this.venusApi = venusApi;
3897
- }
3898
- async getPostInfo() {
3899
- const venusApi = this.venusApi;
3900
- await createMockDelay(MOCK_DELAYS.short);
3901
- return venusApi._mock.currentPostInteractions;
3902
- }
3903
- async openCommentsAsync() {
3904
- await createMockDelay(MOCK_DELAYS.short);
3905
- return {
3906
- opened: true,
3907
- commentsCount: 0
3908
- };
3909
- }
3910
- async toggleFollowAsync() {
3911
- const venusApi = this.venusApi;
3912
- console.log("[Venus Mock] *Toggling follow status");
3913
- await createMockDelay(MOCK_DELAYS.short);
3914
- venusApi._mock.currentPostInteractions.isFollowing = !venusApi._mock.currentPostInteractions.isFollowing;
3915
- const isFollowing = venusApi._mock.currentPostInteractions.isFollowing;
3916
- return {
3917
- isFollowing,
3918
- action: isFollowing ? "followed" : "unfollowed"
3919
- };
3920
- }
3921
- async toggleLikeAsync() {
3922
- const venusApi = this.venusApi;
3923
- await createMockDelay(MOCK_DELAYS.short);
3924
- venusApi._mock.currentPostInteractions.isLiked = !venusApi._mock.currentPostInteractions.isLiked;
3925
- const isLiked = venusApi._mock.currentPostInteractions.isLiked;
3926
- if (isLiked) {
3927
- venusApi._mock.currentPostInteractions.likesCount++;
3928
- } else {
3929
- venusApi._mock.currentPostInteractions.likesCount = Math.max(
3930
- 0,
3931
- venusApi._mock.currentPostInteractions.likesCount - 1
3932
- );
3933
- }
3934
- return {
3935
- isLiked,
3936
- likesCount: venusApi._mock.currentPostInteractions.likesCount,
3937
- action: isLiked ? "liked" : "unliked"
3938
- };
3939
- }
3940
- };
3941
-
3942
- // src/post/RpcPostApi.ts
3943
- var RpcPostApi = class {
4054
+ var RpcPreloaderApi = class {
3944
4055
  constructor(rpcClient) {
3945
4056
  __publicField(this, "rpcClient");
3946
4057
  this.rpcClient = rpcClient;
3947
4058
  }
3948
- getPostInfo() {
3949
- return this.rpcClient.call("H5_GET_POST_INTERACTIONS" /* GET_POST_INTERACTIONS */, {});
4059
+ async showLoadScreen() {
4060
+ await this.rpcClient.call("H5_SHOW_LOAD_SCREEN" /* H5_SHOW_LOAD_SCREEN */);
3950
4061
  }
3951
- openCommentsAsync() {
3952
- return this.rpcClient.call("H5_OPEN_COMMENTS" /* OPEN_COMMENTS */, {});
4062
+ async hideLoadScreen() {
4063
+ await this.rpcClient.call("H5_HIDE_LOAD_SCREEN" /* H5_HIDE_LOAD_SCREEN */);
3953
4064
  }
3954
- toggleFollowAsync() {
3955
- return this.rpcClient.call(
3956
- "H5_TOGGLE_FOLLOW" /* TOGGLE_FOLLOW */,
3957
- {}
3958
- );
4065
+ async setLoaderText(text) {
4066
+ await this.rpcClient.call("H5_SET_LOADER_TEXT" /* H5_SET_LOADER_TEXT */, { text });
3959
4067
  }
3960
- toggleLikeAsync() {
3961
- return this.rpcClient.call("H5_TOGGLE_LIKE" /* TOGGLE_LIKE */, {});
4068
+ async setLoaderProgress(progress) {
4069
+ await this.rpcClient.call("H5_SET_LOADER_PROGRESS" /* H5_SET_LOADER_PROGRESS */, { progress });
3962
4070
  }
3963
4071
  };
3964
4072
 
3965
- // src/post/index.ts
3966
- function initializePost(venusApi, host) {
3967
- venusApi.getPostInteractionsAsync = () => {
3968
- return host.post.getPostInfo();
3969
- };
3970
- venusApi.toggleFollowAsync = () => {
3971
- return host.post.toggleFollowAsync();
3972
- };
3973
- venusApi.toggleLikeAsync = () => {
3974
- return host.post.toggleLikeAsync();
3975
- };
3976
- venusApi.openCommentsAsync = async () => {
3977
- await host.post.openCommentsAsync();
3978
- };
4073
+ // src/game-preloader/index.ts
4074
+ function initializePreloader(venusApi, host) {
4075
+ venusApi.preloader = host.preloader;
3979
4076
  }
3980
4077
 
3981
4078
  // src/social/MockSocialApi.ts
@@ -4080,6 +4177,16 @@ var VenusTransport = class {
4080
4177
  this.isProcessingMessage = false;
4081
4178
  return;
4082
4179
  }
4180
+ if (message.type === "H5_SIMULATION_UPDATE" /* H5_SIMULATION_UPDATE */) {
4181
+ const notification = {
4182
+ type: "rpc-notification",
4183
+ id: message.type,
4184
+ payload: message.data
4185
+ };
4186
+ this.handleNotification(notification);
4187
+ this.isProcessingMessage = false;
4188
+ return;
4189
+ }
4083
4190
  const requestId = messageData.requestId;
4084
4191
  if (!requestId) {
4085
4192
  this.logWarn("No requestId. Ignoring message...");
@@ -4246,294 +4353,6 @@ var VenusTransport = class {
4246
4353
  }
4247
4354
  };
4248
4355
 
4249
- // src/RemoteHost.ts
4250
- init_rooms();
4251
-
4252
- // src/rooms/RpcRoomsApi.ts
4253
- init_VenusRoom();
4254
- var RpcRoomsApi = class {
4255
- constructor(rpcClient) {
4256
- __publicField(this, "rpcClient");
4257
- __publicField(this, "subscriptions");
4258
- __publicField(this, "transportSubscription", null);
4259
- this.rpcClient = rpcClient;
4260
- this.subscriptions = {
4261
- data: {},
4262
- messages: {},
4263
- gameEvents: {},
4264
- allEvents: {}
4265
- };
4266
- }
4267
- /**
4268
- * Get the subscription state for external access (used by setupRoomNotifications)
4269
- */
4270
- getSubscriptions() {
4271
- return this.subscriptions;
4272
- }
4273
- /**
4274
- * Set up room notification routing from the transport
4275
- */
4276
- setupNotifications(transport) {
4277
- const { setupRoomNotifications: setupRoomNotifications2 } = (init_rooms(), __toCommonJS(rooms_exports));
4278
- this.transportSubscription = setupRoomNotifications2(
4279
- transport,
4280
- () => this.getSubscriptions()
4281
- );
4282
- }
4283
- /**
4284
- * Clean up subscriptions and resources
4285
- */
4286
- dispose() {
4287
- if (this.transportSubscription) {
4288
- this.transportSubscription.unsubscribe();
4289
- this.transportSubscription = null;
4290
- console.log("[Venus Rooms] Cleaned up room notification subscription");
4291
- }
4292
- }
4293
- async createRoom(options) {
4294
- const response = await this.rpcClient.call(
4295
- "H5_ROOM_CREATE" /* H5_ROOM_CREATE */,
4296
- {
4297
- options
4298
- }
4299
- );
4300
- if (response.success === false) {
4301
- throw new Error(response.error || "Failed to create room");
4302
- }
4303
- const roomData = response.roomData || response;
4304
- const room = new VenusRoom(roomData);
4305
- return room;
4306
- }
4307
- async joinOrCreateRoom(options) {
4308
- const response = await this.rpcClient.call(
4309
- "H5_ROOM_JOIN_OR_CREATE" /* H5_ROOM_JOIN_OR_CREATE */,
4310
- {
4311
- options
4312
- }
4313
- );
4314
- if (response.success === false) {
4315
- throw new Error(response.error || "Failed to join or create room");
4316
- }
4317
- const data = response.value || response;
4318
- const room = new VenusRoom(data.roomData);
4319
- return {
4320
- action: data.action,
4321
- room,
4322
- playersJoined: data.playersJoined
4323
- };
4324
- }
4325
- async joinRoomByCode(roomCode) {
4326
- const response = await this.rpcClient.call(
4327
- "H5_ROOM_JOIN_BY_CODE" /* H5_ROOM_JOIN_BY_CODE */,
4328
- {
4329
- roomCode
4330
- }
4331
- );
4332
- if (response?.success === false) {
4333
- throw new Error(response.error || "Failed to join room by code");
4334
- }
4335
- const roomData = response.roomData || response;
4336
- const room = new VenusRoom(roomData);
4337
- return room;
4338
- }
4339
- // Get user's rooms with optional filtering
4340
- async getUserRooms(includeArchived = false) {
4341
- const response = await this.rpcClient.call(
4342
- "H5_ROOM_GET_USER_ROOMS" /* H5_ROOM_GET_USER_ROOMS */,
4343
- {
4344
- includeArchived
4345
- }
4346
- );
4347
- if (response?.success === false) {
4348
- throw new Error(response.error || "Failed to get user rooms");
4349
- }
4350
- const rawRooms = response.rooms || [];
4351
- const venusRooms = [];
4352
- for (const roomData of rawRooms) {
4353
- if (!roomData.id) {
4354
- console.warn("getUserRooms: Skipping room with missing ID:", roomData);
4355
- continue;
4356
- }
4357
- try {
4358
- const venusRoom = new VenusRoom(roomData);
4359
- venusRooms.push(venusRoom);
4360
- } catch (error) {
4361
- console.warn(
4362
- "getUserRooms: Failed to create VenusRoom object:",
4363
- error,
4364
- roomData
4365
- );
4366
- }
4367
- }
4368
- return venusRooms;
4369
- }
4370
- async updateData(room, updates, merge = true) {
4371
- const response = await this.rpcClient.call(
4372
- "H5_ROOM_UPDATE_DATA" /* H5_ROOM_UPDATE_DATA */,
4373
- {
4374
- roomId: room.id,
4375
- updates,
4376
- merge
4377
- }
4378
- );
4379
- if (response?.success === false) {
4380
- throw new Error(response.error || "Failed to update room data");
4381
- }
4382
- return response.data;
4383
- }
4384
- async getData(room) {
4385
- const response = await this.rpcClient.call(
4386
- "H5_ROOM_GET_DATA" /* H5_ROOM_GET_DATA */,
4387
- {
4388
- roomId: room.id
4389
- }
4390
- );
4391
- if (response?.success === false) {
4392
- throw new Error(response.error || "Failed to get room data");
4393
- }
4394
- return response.data;
4395
- }
4396
- async sendMessage(venusRoom, messageData) {
4397
- const response = await this.rpcClient.call(
4398
- "H5_ROOM_SEND_MESSAGE" /* H5_ROOM_SEND_MESSAGE */,
4399
- {
4400
- roomId: venusRoom.id,
4401
- message: messageData
4402
- }
4403
- );
4404
- if (response?.success === false) {
4405
- throw new Error(response.error || "Failed to send message");
4406
- }
4407
- return response.messageId;
4408
- }
4409
- async leave(room) {
4410
- const response = await this.rpcClient.call(
4411
- "H5_ROOM_LEAVE" /* H5_ROOM_LEAVE */,
4412
- {
4413
- roomId: room.id
4414
- }
4415
- );
4416
- if (response?.success === false) {
4417
- throw new Error(response.error || "Failed to leave room");
4418
- }
4419
- return response;
4420
- }
4421
- async startGame(room, gameConfig = {}, turnOrder = null) {
4422
- const response = await this.rpcClient.call(
4423
- "H5_ROOM_START_GAME" /* H5_ROOM_START_GAME */,
4424
- {
4425
- roomId: room.id,
4426
- gameConfig,
4427
- turnOrder
4428
- }
4429
- );
4430
- if (response?.success === false) {
4431
- throw new Error(response.error || "Failed to start game");
4432
- }
4433
- return response.data;
4434
- }
4435
- async proposeMove(room, proposalPayload) {
4436
- const response = await this.rpcClient.call(
4437
- "h5:room:proposeMove" /* H5_ROOM_PROPOSE_MOVE */,
4438
- {
4439
- roomId: room.id,
4440
- gameSpecificState: proposalPayload.gameSpecificState,
4441
- moveType: proposalPayload.moveType,
4442
- clientContext: proposalPayload.clientContext,
4443
- clientProposalId: proposalPayload.clientProposalId
4444
- }
4445
- );
4446
- if (response?.success === false) {
4447
- throw new Error(response.error || "Failed to propose move");
4448
- }
4449
- return response.data;
4450
- }
4451
- async validateMove(room, moveId, isValid, reason = null, validatorId = null) {
4452
- console.log(`[Venus Rooms] Validating move ${moveId}: ${isValid}`);
4453
- return { success: true, moveId, isValid, reason };
4454
- }
4455
- async roomSubscribeToGameEvents(room, callback) {
4456
- "game_" + Date.now() + "_" + Math.random().toString(36).substr(2, 9);
4457
- if (!this.subscriptions.gameEvents[room.id]) {
4458
- this.subscriptions.gameEvents[room.id] = [];
4459
- }
4460
- this.subscriptions.gameEvents[room.id].push(callback);
4461
- }
4462
- subscribe(room, options = {}) {
4463
- const subscriptionIds = [];
4464
- const roomId = room.id;
4465
- if (options.onData) {
4466
- const dataSubId = "data_" + Date.now() + "_" + Math.random().toString(36).substr(2, 9);
4467
- if (!this.subscriptions.data[roomId]) {
4468
- this.subscriptions.data[roomId] = [];
4469
- }
4470
- this.subscriptions.data[roomId].push(options.onData);
4471
- subscriptionIds.push({
4472
- type: "data",
4473
- id: dataSubId,
4474
- callback: options.onData
4475
- });
4476
- }
4477
- if (options.onMessages) {
4478
- const msgSubId = "messages_" + Date.now() + "_" + Math.random().toString(36).substr(2, 9);
4479
- if (!this.subscriptions.messages[roomId]) {
4480
- this.subscriptions.messages[roomId] = [];
4481
- }
4482
- this.subscriptions.messages[roomId].push(options.onMessages);
4483
- subscriptionIds.push({
4484
- type: "messages",
4485
- id: msgSubId,
4486
- callback: options.onMessages
4487
- });
4488
- }
4489
- if (options.onMoves || options.onGameEvents) {
4490
- const handler = options.onMoves || options.onGameEvents;
4491
- if (handler) {
4492
- const gameSubId = "game_" + Date.now() + "_" + Math.random().toString(36).substr(2, 9);
4493
- if (!this.subscriptions.gameEvents[roomId]) {
4494
- this.subscriptions.gameEvents[roomId] = [];
4495
- }
4496
- this.subscriptions.gameEvents[roomId].push(handler);
4497
- subscriptionIds.push({
4498
- type: "gameEvents",
4499
- id: gameSubId,
4500
- callback: handler
4501
- });
4502
- }
4503
- }
4504
- 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;
4505
- if (needsSubscription) {
4506
- this.rpcClient.call("H5_ROOM_SUBSCRIBE" /* H5_ROOM_SUBSCRIBE */, {
4507
- roomId,
4508
- subscribeToData: !!options.onData,
4509
- subscribeToMessages: !!options.onMessages,
4510
- subscribeToProposedMoves: !!(options.onMoves || options.onGameEvents)
4511
- }).catch((error) => {
4512
- console.error("Failed to set up room subscription:", error);
4513
- });
4514
- }
4515
- let called = false;
4516
- return () => {
4517
- if (called) return;
4518
- called = true;
4519
- subscriptionIds.forEach((sub) => {
4520
- const bucket = this.subscriptions[sub.type];
4521
- const callbacks = bucket && bucket[roomId] || [];
4522
- const index = callbacks.indexOf(sub.callback);
4523
- if (index > -1) callbacks.splice(index, 1);
4524
- });
4525
- const hasNoCallbacks = (this.subscriptions.data[roomId]?.length ?? 0) === 0 && (this.subscriptions.messages[roomId]?.length ?? 0) === 0 && (this.subscriptions.gameEvents[roomId]?.length ?? 0) === 0;
4526
- if (hasNoCallbacks) {
4527
- this.rpcClient.call("H5_ROOM_UNSUBSCRIBE" /* H5_ROOM_UNSUBSCRIBE */, {
4528
- roomId
4529
- }).catch((error) => {
4530
- console.error("Failed to clean up room subscription:", error);
4531
- });
4532
- }
4533
- };
4534
- }
4535
- };
4536
-
4537
4356
  // src/RemoteHost.ts
4538
4357
  var getCdnBaseUrl = () => {
4539
4358
  return "https://venus-static-01293ak.web.app/";
@@ -4550,9 +4369,9 @@ var RemoteHost = class {
4550
4369
  __publicField(this, "notifications");
4551
4370
  __publicField(this, "popups");
4552
4371
  __publicField(this, "profile");
4372
+ __publicField(this, "system");
4553
4373
  __publicField(this, "cdn");
4554
4374
  __publicField(this, "time");
4555
- __publicField(this, "post");
4556
4375
  __publicField(this, "ai");
4557
4376
  __publicField(this, "haptics");
4558
4377
  __publicField(this, "features");
@@ -4606,10 +4425,12 @@ var RemoteHost = class {
4606
4425
  this.navigation = new RpcNavigationApi(rpcClient, venusApi);
4607
4426
  this.notifications = new RpcNotificationsApi(rpcClient);
4608
4427
  this.popups = new RpcPopupsApi(rpcClient);
4609
- this.profile = new HostProfileApi();
4428
+ this.profile = new HostProfileApi(venusApi);
4429
+ const deviceApi = new HostDeviceApi(venusApi);
4430
+ const environmentApi = new HostEnvironmentApi(venusApi);
4431
+ this.system = new HostSystemApi(deviceApi, environmentApi, venusApi);
4610
4432
  this.cdn = new HostCdnApi(getCdnBaseUrl());
4611
- this.time = new HostTimeApi(rpcClient);
4612
- this.post = new RpcPostApi(rpcClient);
4433
+ this.time = new HostTimeApi(rpcClient, venusApi);
4613
4434
  this.ai = new RpcAiApi(rpcClient);
4614
4435
  this.haptics = new RpcHapticsApi(rpcClient);
4615
4436
  this.features = new RpcFeaturesApi(rpcClient);
@@ -4624,7 +4445,6 @@ var RemoteHost = class {
4624
4445
  venusApi.isMock = () => false;
4625
4446
  this.venusApi.sharedAssets = new RpcSharedAssetsApi(rpcClient, venusApi);
4626
4447
  initializeRoomsApi(this.venusApi, this);
4627
- console.log("[Venus SDK] Remote host created");
4628
4448
  }
4629
4449
  get isInitialized() {
4630
4450
  return this._isInitialized;
@@ -4643,35 +4463,27 @@ var RemoteHost = class {
4643
4463
  );
4644
4464
  transport.instanceId = response.instanceId;
4645
4465
  this.log(`Remote Host Initialized with id: ${transport.instanceId}`);
4646
- if (response.profile) {
4647
- const profile = response.profile;
4648
- const sanitizedProfile = {
4649
- id: profile.id,
4650
- username: profile.username,
4651
- avatarUrl: profile.avatarUrl ?? null,
4652
- isAnonymous: Boolean(profile.isAnonymous)
4653
- };
4654
- if (typeof window !== "undefined") {
4655
- const globalWindow = window;
4656
- const venus = globalWindow.venus || (globalWindow.venus = {});
4657
- venus.profile = sanitizedProfile;
4658
- if (venus._config) {
4659
- venus._config.profile = sanitizedProfile;
4660
- }
4661
- if (venus.config) {
4662
- venus.config.profile = sanitizedProfile;
4663
- }
4664
- }
4665
- }
4466
+ const profile = response.profile;
4467
+ const sanitizedProfile = {
4468
+ id: profile.id,
4469
+ username: profile.username,
4470
+ avatarUrl: profile.avatarUrl ?? null,
4471
+ isAnonymous: Boolean(profile.isAnonymous)
4472
+ };
4473
+ this.venusApi._profileData = sanitizedProfile;
4474
+ this.venusApi._deviceData = response.device;
4475
+ this.venusApi._environmentData = response.environment;
4476
+ this.venusApi._localeData = response.locale;
4477
+ this.venusApi._languageCodeData = response.languageCode;
4666
4478
  this._isInitialized = true;
4667
- this.venusApi.launchParams = response.launchParams || {};
4479
+ this.venusApi.launchParams = response.launchParams;
4668
4480
  await this.rpcClient.call("READY" /* READY */, {});
4669
- const hudInsets = response.hudInsets;
4670
- if (hudInsets) {
4671
- this.venusApi.config.ui.safeArea = hudInsets;
4481
+ const safeArea = response.safeArea;
4482
+ if (safeArea) {
4483
+ this.venusApi._safeAreaData = safeArea;
4672
4484
  }
4673
4485
  return {
4674
- hudInsets,
4486
+ safeArea,
4675
4487
  initializeAsleep: response.initializeAsleep
4676
4488
  };
4677
4489
  }
@@ -4681,49 +4493,120 @@ var RemoteHost = class {
4681
4493
  };
4682
4494
 
4683
4495
  // src/MockHost.ts
4684
- init_rooms();
4685
4496
  var ROOMS_UNAVAILABLE_MESSAGE = "[Venus SDK] Rooms API is only available when running inside the Venus host environment.";
4686
4497
  function createUnavailableRoomsApi() {
4687
4498
  const roomsUnavailableError = () => new Error(ROOMS_UNAVAILABLE_MESSAGE);
4688
4499
  return {
4689
- async createRoom() {
4500
+ async createRoomAsync() {
4690
4501
  throw roomsUnavailableError();
4691
4502
  },
4692
- async joinOrCreateRoom() {
4503
+ async joinOrCreateRoomAsync() {
4693
4504
  throw roomsUnavailableError();
4694
4505
  },
4695
- async getUserRooms() {
4506
+ async joinRoomByCodeAsync() {
4696
4507
  throw roomsUnavailableError();
4697
4508
  },
4698
- async joinRoomByCode() {
4509
+ async getUserRoomsAsync() {
4699
4510
  throw roomsUnavailableError();
4700
4511
  },
4701
- subscribe() {
4512
+ async subscribeAsync() {
4702
4513
  throw roomsUnavailableError();
4703
4514
  },
4704
- async updateData() {
4515
+ async updateRoomDataAsync() {
4705
4516
  throw roomsUnavailableError();
4706
4517
  },
4707
- async getData() {
4518
+ async getRoomDataAsync() {
4708
4519
  throw roomsUnavailableError();
4709
4520
  },
4710
- async sendMessage() {
4521
+ async sendRoomMessageAsync() {
4711
4522
  throw roomsUnavailableError();
4712
4523
  },
4713
- async leave() {
4524
+ async leaveRoomAsync() {
4714
4525
  throw roomsUnavailableError();
4715
4526
  },
4716
- async startGame() {
4527
+ async startRoomGameAsync() {
4717
4528
  throw roomsUnavailableError();
4718
4529
  },
4719
- async proposeMove() {
4530
+ async proposeMoveAsync() {
4720
4531
  throw roomsUnavailableError();
4721
4532
  },
4722
- async validateMove() {
4533
+ async validateMoveAsync() {
4723
4534
  throw roomsUnavailableError();
4724
4535
  }
4725
4536
  };
4726
4537
  }
4538
+ var SIMULATION_UNAVAILABLE_MESSAGE = "[Venus SDK] Simulation API is only available when running inside the Venus host environment.";
4539
+ function createUnavailableSimulationApi() {
4540
+ const simulationUnavailableError = () => new Error(SIMULATION_UNAVAILABLE_MESSAGE);
4541
+ return {
4542
+ isEnabled() {
4543
+ return false;
4544
+ },
4545
+ async getStateAsync() {
4546
+ throw simulationUnavailableError();
4547
+ },
4548
+ async getConfigAsync() {
4549
+ throw simulationUnavailableError();
4550
+ },
4551
+ async executeRecipeAsync() {
4552
+ throw simulationUnavailableError();
4553
+ },
4554
+ async getActiveRunsAsync() {
4555
+ throw simulationUnavailableError();
4556
+ },
4557
+ async collectRecipeAsync() {
4558
+ throw simulationUnavailableError();
4559
+ },
4560
+ async executeScopedRecipeAsync() {
4561
+ throw simulationUnavailableError();
4562
+ },
4563
+ async triggerRecipeChainAsync() {
4564
+ throw simulationUnavailableError();
4565
+ },
4566
+ async getAvailableRecipesAsync() {
4567
+ throw simulationUnavailableError();
4568
+ },
4569
+ async getRecipeRequirementsAsync() {
4570
+ throw simulationUnavailableError();
4571
+ },
4572
+ async getBatchRecipeRequirementsAsync() {
4573
+ throw simulationUnavailableError();
4574
+ },
4575
+ async resolveFieldValueAsync() {
4576
+ throw simulationUnavailableError();
4577
+ },
4578
+ async getEntityMetadataAsync() {
4579
+ throw simulationUnavailableError();
4580
+ },
4581
+ async getSlotContainersAsync() {
4582
+ throw simulationUnavailableError();
4583
+ },
4584
+ async getSlotAssignmentsAsync() {
4585
+ throw simulationUnavailableError();
4586
+ },
4587
+ async assignItemToSlotAsync() {
4588
+ throw simulationUnavailableError();
4589
+ },
4590
+ async removeItemFromSlotAsync() {
4591
+ throw simulationUnavailableError();
4592
+ },
4593
+ async getAvailableItemsAsync() {
4594
+ throw simulationUnavailableError();
4595
+ },
4596
+ async calculatePowerPreviewAsync() {
4597
+ throw simulationUnavailableError();
4598
+ },
4599
+ async validateSlotAssignmentAsync() {
4600
+ throw simulationUnavailableError();
4601
+ },
4602
+ async executeBatchOperationsAsync() {
4603
+ throw simulationUnavailableError();
4604
+ },
4605
+ async subscribeAsync() {
4606
+ throw simulationUnavailableError();
4607
+ }
4608
+ };
4609
+ }
4727
4610
  var MockHost = class {
4728
4611
  constructor(venusApi) {
4729
4612
  __publicField(this, "ads");
@@ -4736,9 +4619,9 @@ var MockHost = class {
4736
4619
  __publicField(this, "notifications");
4737
4620
  __publicField(this, "popups");
4738
4621
  __publicField(this, "profile");
4622
+ __publicField(this, "system");
4739
4623
  __publicField(this, "cdn");
4740
4624
  __publicField(this, "time");
4741
- __publicField(this, "post");
4742
4625
  __publicField(this, "ai");
4743
4626
  __publicField(this, "haptics");
4744
4627
  __publicField(this, "features");
@@ -4770,15 +4653,17 @@ var MockHost = class {
4770
4653
  this.navigation = new MockNavigationApi(venusApi);
4771
4654
  this.notifications = new MockNotificationsApi(venusApi);
4772
4655
  this.popups = new MockPopupsApi(this._overlay);
4773
- this.profile = new MockProfileApi();
4774
- this.cdn = new MockCdnApi();
4656
+ this.profile = new MockProfileApi(venusApi);
4657
+ const deviceApi = new MockDeviceApi(venusApi);
4658
+ const environmentApi = new MockEnvironmentApi(venusApi);
4659
+ this.system = new MockSystemApi(deviceApi, environmentApi, venusApi);
4660
+ this.cdn = new MockCdnApi(venusApi);
4775
4661
  this.time = new MockTimeApi(venusApi);
4776
- this.post = new MockPostApi(venusApi);
4777
4662
  this.ai = new MockAiApi();
4778
4663
  this.haptics = new MockHapticsApi(venusApi);
4779
4664
  this.features = new MockFeaturesApi();
4780
4665
  this.lifecycle = this._mockLifecyclesApi;
4781
- this.simulation = new MockSimulationApi();
4666
+ this.simulation = createUnavailableSimulationApi();
4782
4667
  this.rooms = createUnavailableRoomsApi();
4783
4668
  this.logging = new MockLoggingApi();
4784
4669
  this.iap = new MockIapApi();
@@ -4794,40 +4679,17 @@ var MockHost = class {
4794
4679
  }
4795
4680
  initialize(options) {
4796
4681
  this._isInitialized = true;
4797
- const controls = this.updateUiControls();
4682
+ this.venusApi._profileData = this.profile.getCurrentProfile();
4683
+ this.venusApi._deviceData = this.system.getDevice();
4684
+ this.venusApi._environmentData = this.system.getEnvironment();
4685
+ this.venusApi._localeData = this.venusApi._mock?.locale || "en-US";
4686
+ this.venusApi._languageCodeData = this.venusApi._mock?.languageCode || "en";
4798
4687
  return Promise.resolve({
4799
4688
  initializeAsleep: false,
4800
- hudInsets: {
4801
- top: controls.feedHeader.height,
4802
- bottom: 0,
4803
- left: 0,
4804
- right: 0
4805
- }
4689
+ safeArea: this.venusApi._safeAreaData
4806
4690
  });
4807
4691
  }
4808
- updateUiControls() {
4809
- const controls = {
4810
- closeButton: { x: 16, y: 16, width: 32, height: 32 },
4811
- menuButton: {
4812
- x: window.innerWidth - 48,
4813
- y: 16,
4814
- width: 32,
4815
- height: 32
4816
- },
4817
- feedHeader: { x: 0, y: 0, width: window.innerWidth, height: 56 },
4818
- playButton: {
4819
- x: 0,
4820
- y: window.innerHeight - 60,
4821
- width: window.innerWidth,
4822
- height: 60
4823
- }
4824
- };
4825
- return controls;
4826
- }
4827
4692
  createOverlay() {
4828
- const venusApi = this.venusApi;
4829
- venusApi.config.ui.controls = this.updateUiControls();
4830
- const uiControls = venusApi.config.ui.controls;
4831
4693
  const overlayContainer = document.createElement("div");
4832
4694
  overlayContainer.id = "venus-mock-overlay";
4833
4695
  overlayContainer.style.cssText = `
@@ -4843,7 +4705,7 @@ var MockHost = class {
4843
4705
  const menuButton = this.createOverlayButton(
4844
4706
  "close",
4845
4707
  "Menu",
4846
- uiControls.menuButton,
4708
+ { x: window.innerWidth - 48, y: 16, width: 32, height: 32 },
4847
4709
  () => {
4848
4710
  this.handleMenuButtonClicked();
4849
4711
  },
@@ -5072,17 +4934,13 @@ var MockHost = class {
5072
4934
  return button;
5073
4935
  }
5074
4936
  updateOverlayLayout() {
5075
- const venusApi = this.venusApi;
5076
4937
  const overlay = this._overlay;
5077
- venusApi.config.ui.controls = this.updateUiControls();
5078
- const uiControls = venusApi.config.ui.controls;
5079
4938
  const menuBtn = overlay.elements.menuButton;
5080
- const menuPos = uiControls.menuButton;
5081
- menuBtn.style.left = `${menuPos.x}px`;
5082
- menuBtn.style.top = `${menuPos.y}px`;
5083
- menuBtn.style.width = `${menuPos.width}px`;
5084
- menuBtn.style.minWidth = `${menuPos.width}px`;
5085
- menuBtn.style.height = `${menuPos.height}px`;
4939
+ menuBtn.style.left = `${window.innerWidth - 48}px`;
4940
+ menuBtn.style.top = "16px";
4941
+ menuBtn.style.width = "32px";
4942
+ menuBtn.style.minWidth = "32px";
4943
+ menuBtn.style.height = "32px";
5086
4944
  }
5087
4945
  triggerLifecycleEvent(name) {
5088
4946
  console.log("Trigger Lifecycle Event: ", name);
@@ -5273,10 +5131,8 @@ var MockHost = class {
5273
5131
  // src/Host.ts
5274
5132
  function createHost(venusApi, isMock) {
5275
5133
  if (isMock) {
5276
- console.log("[Venus SDK] Creating Local Host");
5277
5134
  return new MockHost(venusApi);
5278
5135
  } else {
5279
- console.log("[Venus SDK] Creating Remote Host");
5280
5136
  return new RemoteHost(venusApi);
5281
5137
  }
5282
5138
  }
@@ -5289,6 +5145,6 @@ function initializeSocial(venusApi, host) {
5289
5145
  };
5290
5146
  }
5291
5147
 
5292
- export { HapticFeedbackStyle, HostCdnApi, HostProfileApi, HostTimeApi, MockAdsApi, MockAiApi, MockAnalyticsApi, MockAvatarApi, MockCdnApi, MockFeaturesApi, MockHapticsApi, MockIapApi, MockLeaderboardApi, MockLifecycleApi, MockLoggingApi, MockNavigationApi, MockNotificationsApi, MockPopupsApi, MockPreloaderApi, MockProfileApi, MockSharedAssetsApi, MockSimulationApi, MockSocialApi, MockStorageApi, MockTimeApi, RemoteHost, RpcAdsApi, RpcAiApi, RpcAnalyticsApi, RpcAvatarApi, RpcClient, RpcFeaturesApi, RpcHapticsApi, RpcIapApi, RpcLeaderboardApi, RpcLifecycleApi, RpcLoggingApi, RpcNavigationApi, RpcNotificationsApi, RpcPopupsApi, RpcPreloaderApi, RpcSharedAssetsApi, RpcSimulationApi, RpcSocialApi, RpcStorageApi, SDK_VERSION, VenusMessageId, VenusRoom, createHost, createMockStorageApi, init_rooms, initializeAds, initializeAi, initializeAnalytics, initializeAvatar3d, initializeCdn, initializeFeaturesApi, initializeHaptics, initializeIap, initializeLeaderboard, initializeLifecycleApi, initializeLocalNotifications, initializeLoggingApi, initializePopups, initializePost, initializePreloader, initializeProfile, initializeRoomsApi, initializeSimulation, initializeSocial, initializeStackNavigation, initializeStorage, initializeTime, isPacificDaylightTime, setupRoomNotifications };
5293
- //# sourceMappingURL=chunk-PXWCNWJ6.mjs.map
5294
- //# sourceMappingURL=chunk-PXWCNWJ6.mjs.map
5148
+ export { DEFAULT_SHARED_LIB_CDN_BASE, EMBEDDED_LIBRARIES, EMBEDDED_LIBRARY_BY_KEY, HASH_ALGORITHM_NODE, HASH_ALGORITHM_WEB_CRYPTO, HapticFeedbackStyle, HostCdnApi, HostDeviceApi, HostEnvironmentApi, HostProfileApi, HostSystemApi, HostTimeApi, MODULE_TO_LIBRARY_SPECIFIERS, MockAdsApi, MockAiApi, MockAnalyticsApi, MockAvatarApi, MockCdnApi, MockDeviceApi, MockEnvironmentApi, MockFeaturesApi, MockHapticsApi, MockIapApi, MockLeaderboardApi, MockLifecycleApi, MockLoggingApi, MockNavigationApi, MockNotificationsApi, MockPopupsApi, MockPreloaderApi, MockProfileApi, MockSharedAssetsApi, MockSocialApi, MockStorageApi, MockSystemApi, MockTimeApi, RemoteHost, RpcAdsApi, RpcAiApi, RpcAnalyticsApi, RpcAvatarApi, RpcClient, RpcFeaturesApi, RpcHapticsApi, RpcIapApi, RpcLeaderboardApi, RpcLifecycleApi, RpcLoggingApi, RpcNavigationApi, RpcNotificationsApi, RpcPopupsApi, RpcPreloaderApi, RpcRoomsApi, RpcSharedAssetsApi, RpcSimulationApi, RpcSocialApi, RpcStorageApi, SDK_VERSION, VenusMessageId, VenusRoom, base64ToArrayBuffer, base64ToUtf8, computeScoreHash, createHost, createMockStorageApi, getLibraryDefinition, initializeAds, initializeAi, initializeAnalytics, initializeAvatar3d, initializeCdn, initializeFeaturesApi, initializeHaptics, initializeIap, initializeLeaderboard, initializeLifecycleApi, initializeLocalNotifications, initializeLoggingApi, initializePopups, initializePreloader, initializeProfile, initializeRoomsApi, initializeSimulation, initializeSocial, initializeStackNavigation, initializeStorage, initializeSystem, initializeTime, isPacificDaylightTime, setupRoomNotifications };
5149
+ //# sourceMappingURL=chunk-AGXMORDL.mjs.map
5150
+ //# sourceMappingURL=chunk-AGXMORDL.mjs.map