@series-inc/venus-sdk 2.4.1 → 2.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,9 @@
1
1
  'use strict';
2
2
 
3
3
  var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
7
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6
8
  var __esm = (fn, res) => function __init() {
7
9
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
@@ -10,6 +12,15 @@ var __export = (target, all) => {
10
12
  for (var name in all)
11
13
  __defProp(target, name, { get: all[name], enumerable: true });
12
14
  };
15
+ var __copyProps = (to, from, except, desc) => {
16
+ if (from && typeof from === "object" || typeof from === "function") {
17
+ for (let key of __getOwnPropNames(from))
18
+ if (!__hasOwnProp.call(to, key) && key !== except)
19
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
20
+ }
21
+ return to;
22
+ };
23
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
13
24
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
14
25
 
15
26
  // src/venus-api/systems/core.js
@@ -100,6 +111,221 @@ var init_core = __esm({
100
111
  }
101
112
  });
102
113
 
114
+ // src/rooms/RoomsApi.ts
115
+ var init_RoomsApi = __esm({
116
+ "src/rooms/RoomsApi.ts"() {
117
+ }
118
+ });
119
+
120
+ // src/rooms/VenusRoom.ts
121
+ var VenusRoom;
122
+ var init_VenusRoom = __esm({
123
+ "src/rooms/VenusRoom.ts"() {
124
+ VenusRoom = class {
125
+ constructor(roomData) {
126
+ __publicField(this, "id");
127
+ __publicField(this, "name");
128
+ __publicField(this, "players");
129
+ __publicField(this, "maxPlayers");
130
+ __publicField(this, "gameType");
131
+ __publicField(this, "appId");
132
+ __publicField(this, "type");
133
+ __publicField(this, "createdBy");
134
+ __publicField(this, "createdAt");
135
+ __publicField(this, "updatedAt");
136
+ __publicField(this, "isPrivate");
137
+ __publicField(this, "currentPlayers");
138
+ __publicField(this, "status");
139
+ __publicField(this, "customMetadata");
140
+ __publicField(this, "admins");
141
+ __publicField(this, "roomCode");
142
+ __publicField(this, "description");
143
+ __publicField(this, "data");
144
+ __publicField(this, "version");
145
+ __publicField(this, "_subscriptions", /* @__PURE__ */ new Map());
146
+ this.id = roomData.id;
147
+ this.name = roomData.name;
148
+ this.players = roomData.currentPlayers || [];
149
+ this.maxPlayers = roomData.maxPlayers;
150
+ this.gameType = roomData.gameType;
151
+ this.appId = roomData.appId;
152
+ this.type = roomData.type;
153
+ this.createdBy = roomData.createdBy;
154
+ this.createdAt = roomData.createdAt;
155
+ this.updatedAt = roomData.updatedAt;
156
+ this.isPrivate = roomData.isPrivate;
157
+ this.currentPlayers = roomData.currentPlayers || [];
158
+ this.status = roomData.status;
159
+ this.customMetadata = roomData.customMetadata || {};
160
+ this.admins = roomData.admins || [];
161
+ this.roomCode = roomData.roomCode;
162
+ this.description = roomData.description;
163
+ this.data = roomData.data || {};
164
+ this.version = roomData.version;
165
+ console.log(`VenusRoom: Created room object for ${this.id}`, {
166
+ hasCustomMetadata: !!this.customMetadata,
167
+ hasGameState: !!this.customMetadata?.rules?.gameState,
168
+ gamePhase: this.customMetadata?.rules?.gameState?.phase,
169
+ currentPlayer: this.customMetadata?.rules?.gameState?.currentPlayer
170
+ });
171
+ }
172
+ updateFromRoomData(newRoomData) {
173
+ if (newRoomData.id === this.id) {
174
+ this.name = newRoomData.name || this.name;
175
+ this.players = newRoomData.currentPlayers || this.players;
176
+ this.maxPlayers = newRoomData.maxPlayers || this.maxPlayers;
177
+ this.gameType = newRoomData.gameType || this.gameType;
178
+ this.currentPlayers = newRoomData.currentPlayers || this.currentPlayers;
179
+ this.customMetadata = newRoomData.customMetadata || this.customMetadata;
180
+ this.data = newRoomData.data || this.data;
181
+ this.status = newRoomData.status || this.status;
182
+ this.updatedAt = newRoomData.updatedAt || this.updatedAt;
183
+ console.log(`VenusRoom: Updated room object ${this.id} with fresh data`, {
184
+ hasCustomMetadata: !!this.customMetadata,
185
+ hasGameState: !!this.customMetadata?.rules?.gameState,
186
+ gamePhase: this.customMetadata?.rules?.gameState?.phase,
187
+ currentPlayer: this.customMetadata?.rules?.gameState?.currentPlayer
188
+ });
189
+ }
190
+ }
191
+ };
192
+ }
193
+ });
194
+
195
+ // src/rooms/index.ts
196
+ var rooms_exports = {};
197
+ __export(rooms_exports, {
198
+ VenusRoom: () => VenusRoom,
199
+ initializeRoomsApi: () => initializeRoomsApi,
200
+ setupRoomNotifications: () => setupRoomNotifications
201
+ });
202
+ function bindMethod(target, targetKey, source, sourceKey) {
203
+ const key = sourceKey ?? targetKey;
204
+ const fn = source?.[key];
205
+ if (typeof fn === "function") {
206
+ target[targetKey] = fn.bind(source);
207
+ return true;
208
+ }
209
+ return false;
210
+ }
211
+ function setupRoomNotifications(transport, getSubscriptions) {
212
+ console.log("[Venus Rooms] Setting up room notification listeners");
213
+ return transport.onVenusMessage((message) => {
214
+ const subscriptions = getSubscriptions();
215
+ if (!subscriptions) {
216
+ return;
217
+ }
218
+ if (message.type === "H5_ROOM_DATA_UPDATED") {
219
+ const messageData = message.data;
220
+ const { roomId, roomData } = messageData;
221
+ if (!roomId) return;
222
+ const callbacks = subscriptions.data?.[roomId] || [];
223
+ const allEventsCallbacks = subscriptions.allEvents?.[roomId] || [];
224
+ console.log(`[Venus Rooms] \u{1F514} Room data updated for ${roomId}, notifying ${callbacks.length} callbacks`, roomData);
225
+ callbacks.forEach((callback) => {
226
+ try {
227
+ callback(roomData);
228
+ } catch (error) {
229
+ console.error("[Venus Rooms] Error in room data callback:", error);
230
+ throw error;
231
+ }
232
+ });
233
+ allEventsCallbacks.forEach((callback) => {
234
+ try {
235
+ callback({ type: message.type, ...messageData });
236
+ } catch (error) {
237
+ console.error("[Venus Rooms] Error in allEvents callback:", error);
238
+ throw error;
239
+ }
240
+ });
241
+ }
242
+ if (message.type === "H5_ROOM_MESSAGE_RECEIVED" || message.type === "H5_ROOM_MESSAGE_UPDATED" || message.type === "H5_ROOM_MESSAGE_DELETED") {
243
+ const messageData = message.data;
244
+ const { roomId } = messageData;
245
+ if (!roomId) return;
246
+ const callbacks = subscriptions.messages?.[roomId] || [];
247
+ const allEventsCallbacks = subscriptions.allEvents?.[roomId] || [];
248
+ console.log(`[Venus Rooms] \u{1F514} Room message event for ${roomId}, notifying ${callbacks.length} callbacks`);
249
+ callbacks.forEach((callback) => {
250
+ try {
251
+ callback(messageData);
252
+ } catch (error) {
253
+ console.error("[Venus Rooms] Error in room message callback:", error);
254
+ throw error;
255
+ }
256
+ });
257
+ allEventsCallbacks.forEach((callback) => {
258
+ try {
259
+ callback({ type: message.type, ...messageData });
260
+ } catch (error) {
261
+ console.error("[Venus Rooms] Error in allEvents callback:", error);
262
+ throw error;
263
+ }
264
+ });
265
+ }
266
+ if (message.type === "app:h5:proposedMoveValidationUpdated") {
267
+ const messageData = message.data;
268
+ const { roomId } = messageData;
269
+ if (!roomId) return;
270
+ const callbacks = subscriptions.gameEvents?.[roomId] || [];
271
+ const allEventsCallbacks = subscriptions.allEvents?.[roomId] || [];
272
+ console.log(`[Venus Rooms] \u{1F514} Proposed move validation updated for ${roomId}, notifying ${callbacks.length} callbacks`);
273
+ callbacks.forEach((callback) => {
274
+ try {
275
+ callback(messageData);
276
+ } catch (error) {
277
+ console.error("[Venus Rooms] Error in game event callback:", error);
278
+ throw error;
279
+ }
280
+ });
281
+ allEventsCallbacks.forEach((callback) => {
282
+ try {
283
+ callback({ type: message.type, ...messageData });
284
+ } catch (error) {
285
+ console.error("[Venus Rooms] Error in allEvents callback:", error);
286
+ throw error;
287
+ }
288
+ });
289
+ }
290
+ });
291
+ }
292
+ function initializeRoomsApi(venusApi, host) {
293
+ const roomsApi = host?.rooms;
294
+ if (!roomsApi) {
295
+ console.warn(
296
+ "[Venus SDK] Host did not provide a rooms implementation. Rooms API will be unavailable."
297
+ );
298
+ return;
299
+ }
300
+ const venus = venusApi;
301
+ const existingNamespace = venus.rooms || {};
302
+ const roomsNamespace = Object.assign({}, existingNamespace);
303
+ const namespaceBindings = [
304
+ ["create", "createRoom"],
305
+ ["joinOrCreate", "joinOrCreateRoom"],
306
+ ["joinByCode", "joinRoomByCode"],
307
+ ["list", "getUserRooms"],
308
+ ["subscribeToRoom", "subscribe"],
309
+ ["updateRoomData", "updateData"],
310
+ ["getRoomData", "getData"],
311
+ ["sendRoomMessage", "sendMessage"],
312
+ ["leaveRoom", "leave"],
313
+ ["startRoomGame", "startGame"],
314
+ ["proposeMove"],
315
+ ["validateMove"]
316
+ ];
317
+ namespaceBindings.forEach(([targetKey, sourceKey]) => {
318
+ bindMethod(roomsNamespace, targetKey, roomsApi, sourceKey);
319
+ });
320
+ venus.rooms = roomsNamespace;
321
+ }
322
+ var init_rooms = __esm({
323
+ "src/rooms/index.ts"() {
324
+ init_RoomsApi();
325
+ init_VenusRoom();
326
+ }
327
+ });
328
+
103
329
  // src/storage/MockStorageApi.ts
104
330
  function createMockStorageApi(storageType, appUrl) {
105
331
  const appIdentifier = appUrl ? generateAppIdentifier(appUrl) : null;
@@ -349,7 +575,11 @@ var RpcAdsApi = class {
349
575
  return response.shown;
350
576
  }
351
577
  async isRewardedAdReadyAsync() {
352
- return true;
578
+ console.log(`[Venus SDK] [RpcAdsApi] isRewardedAdReadyAsync`);
579
+ const response = await this.rpcClient.call(
580
+ "H5_IS_REWARDED_AD_READY" /* IS_REWARDED_AD_READY */
581
+ );
582
+ return response.ready;
353
583
  }
354
584
  async showRewardedAdAsync() {
355
585
  console.log("[Venus SDK] [RpcAdsApi] showRewardedAdAsync");
@@ -387,6 +617,8 @@ var MockAdsApi = class {
387
617
  }
388
618
  async showInterstitialAd() {
389
619
  this.log(`[MockAdsApi] showInterstitialAd`);
620
+ await this.mockOverlay.showAdOverlay();
621
+ this.log("[MockAdsApi] interstitial ad shown");
390
622
  return true;
391
623
  }
392
624
  log(message, ...args) {
@@ -736,7 +968,7 @@ var MockNotificationsApi = class {
736
968
  __publicField(this, "venusApi");
737
969
  this.venusApi = venusApi;
738
970
  }
739
- async cancelLocalNotification(notificationId) {
971
+ async cancelNotification(notificationId) {
740
972
  const venusApi = this.venusApi;
741
973
  if (isWebPlatform()) {
742
974
  console.log(
@@ -777,16 +1009,16 @@ var MockNotificationsApi = class {
777
1009
  const isEnabled = venusApi._mock.notificationsEnabled !== false;
778
1010
  return isEnabled;
779
1011
  }
780
- async scheduleLocalNotification(title, body, options) {
1012
+ async scheduleAsync(options) {
781
1013
  if (isWebPlatform()) {
782
1014
  console.log(
783
1015
  "[Venus Mock] Notifications not supported on web platform, simulating success"
784
1016
  );
785
1017
  console.info(
786
1018
  "\u{1F514} [Venus Mock] Notification would be scheduled:",
787
- title || "Untitled",
1019
+ options.title || "Untitled",
788
1020
  "\n Body:",
789
- body || "No body",
1021
+ options.body || "No body",
790
1022
  "\n This is a simulation - real notifications require a native platform."
791
1023
  );
792
1024
  const mockId = `mock-web-notification-${Date.now()}`;
@@ -807,9 +1039,11 @@ var MockNotificationsApi = class {
807
1039
  venusApi._mock.scheduledNotifications = {};
808
1040
  }
809
1041
  venusApi._mock.scheduledNotifications[notificationId] = {
810
- ...options,
811
1042
  id: notificationId,
812
- createdAt: Date.now()
1043
+ title: options.title,
1044
+ body: options.body,
1045
+ payload: options.payload,
1046
+ trigger: options.trigger
813
1047
  };
814
1048
  setTimeout(() => {
815
1049
  resolve(notificationId);
@@ -832,36 +1066,76 @@ var MockNotificationsApi = class {
832
1066
  }
833
1067
  };
834
1068
 
835
- // src/notifications/index.ts
836
- function initializeLocalNotifications(venusApi, host) {
837
- venusApi.setLocalNotifEnabledAsync = async (enable) => {
838
- await host.notifications.setLocalNotificationsEnabled(enable);
839
- };
840
- venusApi.isLocalNotifEnabledAsync = async () => {
841
- return host.notifications.isLocalNotificationsEnabled();
842
- };
843
- venusApi.getAllLocalNotifsAsync = async () => {
844
- return host.notifications.getAllScheduledLocalNotifications();
845
- };
846
- venusApi.cancelLocalNotifAsync = async (notificationId) => {
847
- await host.notifications.cancelLocalNotification(notificationId);
848
- };
849
- venusApi.scheduleLocalNotifAsync = async (options) => {
850
- const id = await host.notifications.scheduleLocalNotification(
851
- options.title,
852
- options.body,
1069
+ // src/notifications/RpcNotificationsApi.ts
1070
+ var RpcNotificationsApi = class {
1071
+ constructor(rpcClient) {
1072
+ __publicField(this, "rpcClient");
1073
+ this.rpcClient = rpcClient;
1074
+ }
1075
+ async scheduleAsync(options) {
1076
+ const request = {
1077
+ title: options.title,
1078
+ body: options.body,
1079
+ data: options.payload,
1080
+ key: options.groupId,
1081
+ priority: options.priority || 1,
1082
+ trigger: options.trigger
1083
+ };
1084
+ const response = await this.rpcClient.call(
1085
+ "H5_SCHEDULE_LOCAL_NOTIFICATION" /* SCHEDULE_LOCAL_NOTIFICATION */,
1086
+ request
1087
+ );
1088
+ if (response.scheduled) {
1089
+ return response.id;
1090
+ }
1091
+ return null;
1092
+ }
1093
+ async cancelNotification(id) {
1094
+ const result = await this.rpcClient.call(
1095
+ "H5_CANCEL_LOCAL_NOTIFICATION" /* CANCEL_LOCAL_NOTIFICATION */,
853
1096
  {
854
- trigger: options.trigger,
855
- priority: options.priority,
856
- groupId: options.groupId,
857
- payload: options.payload
1097
+ id
858
1098
  }
859
1099
  );
860
- if (id) {
861
- return id;
862
- }
863
- return "";
864
- };
1100
+ return result.canceled;
1101
+ }
1102
+ async getAllScheduledLocalNotifications() {
1103
+ const response = await this.rpcClient.call(
1104
+ "H5_GET_ALL_SCHEDULED_LOCAL_NOTIFICATIONS" /* GET_ALL_SCHEDULED_LOCAL_NOTIFICATIONS */,
1105
+ {}
1106
+ );
1107
+ const notifications = response.notifications.map((notif) => {
1108
+ return {
1109
+ id: notif.identifier,
1110
+ title: notif.content.title,
1111
+ body: notif.content.body,
1112
+ payload: notif.content.data,
1113
+ trigger: notif.trigger
1114
+ };
1115
+ });
1116
+ return notifications;
1117
+ }
1118
+ async isLocalNotificationsEnabled() {
1119
+ const response = await this.rpcClient.call(
1120
+ "H5_IS_LOCAL_NOTIFICATIONS_ENABLED" /* IS_LOCAL_NOTIFICATIONS_ENABLED */,
1121
+ {}
1122
+ );
1123
+ return response.enabled;
1124
+ }
1125
+ async setLocalNotificationsEnabled(enabled) {
1126
+ const response = await this.rpcClient.call(
1127
+ "H5_SET_LOCAL_NOTIFICATIONS_ENABLED" /* SET_LOCAL_NOTIFICATIONS_ENABLED */,
1128
+ {
1129
+ enabled
1130
+ }
1131
+ );
1132
+ return response.enabled;
1133
+ }
1134
+ };
1135
+
1136
+ // src/notifications/index.ts
1137
+ function initializeLocalNotifications(venusApi, host) {
1138
+ venusApi.notifications = host.notifications;
865
1139
  }
866
1140
 
867
1141
  // src/time/utils.ts
@@ -1734,1003 +2008,67 @@ function initializeStackNavigation(venusApi, host) {
1734
2008
  var RpcAiApi = class {
1735
2009
  constructor(rpcClient) {
1736
2010
  __publicField(this, "rpcClient");
1737
- this.rpcClient = rpcClient;
1738
- }
1739
- async requestChatCompletionAsync(request) {
1740
- const response = await this.rpcClient.call(
1741
- "H5_AI_CHAT_COMPLETION" /* AI_CHAT_COMPLETION */,
1742
- {
1743
- request: (() => {
1744
- const { apiKey, ...requestWithoutApiKey } = request;
1745
- return requestWithoutApiKey;
1746
- })()
1747
- }
1748
- );
1749
- return response;
1750
- }
1751
- async getAvailableCompletionModels() {
1752
- const response = await this.rpcClient.call(
1753
- "H5_AI_GET_AVAILABLE_MODELS" /* AI_GET_AVAILABLE_MODELS */
1754
- );
1755
- return response;
1756
- }
1757
- };
1758
-
1759
- // src/ai/MockAiApi.ts
1760
- var MockAiApi = class {
1761
- async requestChatCompletionAsync(request) {
1762
- const { apiKey, ...requestBody } = request;
1763
- if (!apiKey) {
1764
- throw new Error("An API key is required for a chat completion request when developing locally.");
1765
- }
1766
- const response = await fetch("https://series.ullm.rho.live/api/v1/completions", {
1767
- method: "POST",
1768
- headers: {
1769
- "Content-Type": "application/json",
1770
- "Authorization": `Bearer ${apiKey}`
1771
- },
1772
- body: JSON.stringify(requestBody)
1773
- });
1774
- if (!response.ok) {
1775
- throw new Error(`HTTP error! status: ${response.status}`);
1776
- }
1777
- const data = await response.json();
1778
- return data;
1779
- }
1780
- async getAvailableCompletionModels() {
1781
- const response = await fetch("https://series.ullm.rho.live/api/v1/models", {
1782
- method: "GET",
1783
- headers: {
1784
- "Content-Type": "application/json"
1785
- }
1786
- });
1787
- if (!response.ok) {
1788
- throw new Error(`HTTP error! status: ${response.status}`);
1789
- }
1790
- const data = await response.json();
1791
- return data;
1792
- }
1793
- };
1794
-
1795
- // src/ai/index.ts
1796
- function initializeAi(venusApi, host) {
1797
- venusApi.ai = host.ai;
1798
- }
1799
-
1800
- // src/venus-api/systems/rooms.js
1801
- init_core();
1802
- var mockRooms = /* @__PURE__ */ new Map();
1803
- var mockMessages = /* @__PURE__ */ new Map();
1804
- var mockRoomMoves = /* @__PURE__ */ new Map();
1805
- var mockSubscriptions = /* @__PURE__ */ new Map();
1806
- function generateRoomId() {
1807
- return "room_" + Date.now() + "_" + Math.random().toString(36).substr(2, 9);
1808
- }
1809
- function generateMessageId() {
1810
- return "msg_" + Date.now() + "_" + Math.random().toString(36).substr(2, 9);
1811
- }
1812
- function generateRoomCode() {
1813
- const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
1814
- let code = "";
1815
- for (let i = 0; i < 6; i++) {
1816
- code += characters.charAt(Math.floor(Math.random() * characters.length));
1817
- }
1818
- return code;
1819
- }
1820
- function broadcastEvent(roomId, eventType, eventData) {
1821
- console.log(`[Venus Mock Rooms] Broadcasting ${eventType} for room ${roomId}:`, eventData);
1822
- for (const [instanceId, subscriptions] of mockSubscriptions.entries()) {
1823
- const roomSubscriptions = subscriptions.get(roomId);
1824
- if (roomSubscriptions) {
1825
- setTimeout(() => {
1826
- if (roomSubscriptions.onRoomDataUpdated && eventType === "room_data_updated") {
1827
- roomSubscriptions.onRoomDataUpdated(eventData);
1828
- }
1829
- if (roomSubscriptions.onMessageReceived && eventType === "message_received") {
1830
- roomSubscriptions.onMessageReceived(eventData);
1831
- }
1832
- if (roomSubscriptions.onPlayerJoined && eventType === "player_joined") {
1833
- roomSubscriptions.onPlayerJoined(eventData);
1834
- }
1835
- if (roomSubscriptions.onPlayerLeft && eventType === "player_left") {
1836
- roomSubscriptions.onPlayerLeft(eventData);
1837
- }
1838
- if (roomSubscriptions.onGameStarted && eventType === "game_started") {
1839
- roomSubscriptions.onGameStarted(eventData);
1840
- }
1841
- if (roomSubscriptions.onTurnChanged && eventType === "turn_changed") {
1842
- roomSubscriptions.onTurnChanged(eventData);
1843
- }
1844
- if (roomSubscriptions.onOptimisticGameStateUpdated && eventType === "app:h5:optimisticGameStateUpdated") {
1845
- roomSubscriptions.onOptimisticGameStateUpdated(eventData);
1846
- }
1847
- if (roomSubscriptions.onProposedMoveValidationUpdated && eventType === "app:h5:proposedMoveValidationUpdated") {
1848
- roomSubscriptions.onProposedMoveValidationUpdated(eventData);
1849
- }
1850
- }, 50);
1851
- }
1852
- }
1853
- }
1854
- var MockVenusRoom = class {
1855
- constructor(roomData) {
1856
- this.id = roomData.id;
1857
- this.roomId = roomData.id;
1858
- this.name = roomData.name;
1859
- this.players = roomData.currentPlayers || [];
1860
- this.maxPlayers = roomData.maxPlayers;
1861
- this.gameType = roomData.gameType;
1862
- this._subscriptions = /* @__PURE__ */ new Map();
1863
- this.appId = roomData.appId;
1864
- this.type = roomData.type;
1865
- this.createdBy = roomData.createdBy;
1866
- this.createdAt = roomData.createdAt;
1867
- this.updatedAt = roomData.updatedAt;
1868
- this.isPrivate = roomData.isPrivate;
1869
- this.currentPlayers = roomData.currentPlayers || [];
1870
- this.status = roomData.status;
1871
- this.customMetadata = roomData.customMetadata || {};
1872
- this.admins = roomData.admins || [];
1873
- this.roomCode = roomData.roomCode;
1874
- this.description = roomData.description;
1875
- this.data = roomData.data || {};
1876
- this.version = roomData.version;
1877
- console.log(`[Venus Mock VenusRoom] Created room object for ${this.id}`, {
1878
- hasCustomMetadata: !!this.customMetadata,
1879
- hasGameState: !!this.customMetadata?.rules?.gameState,
1880
- gamePhase: this.customMetadata?.rules?.gameState?.phase,
1881
- currentPlayer: this.customMetadata?.rules?.gameState?.currentPlayer
1882
- });
1883
- }
1884
- // Update room data
1885
- async updateData(updates, merge = true) {
1886
- return roomsMock.updateRoomData(this.roomId, updates, merge);
1887
- }
1888
- // Get room data
1889
- async getData() {
1890
- return roomsMock.getRoomData(this.roomId);
1891
- }
1892
- // Send message
1893
- async sendMessage(messageData) {
1894
- return roomsMock.sendMessage(this.roomId, messageData);
1895
- }
1896
- // Subscribe to room data changes
1897
- subscribeToData(callback) {
1898
- return roomsMock.subscribeToRoom(this.roomId, {
1899
- onRoomDataUpdated: callback
1900
- });
1901
- }
1902
- // Subscribe to messages
1903
- subscribeToMessages(callback) {
1904
- return roomsMock.subscribeToRoom(this.roomId, {
1905
- onMessageReceived: callback
1906
- });
1907
- }
1908
- // Leave room
1909
- async leave() {
1910
- this._subscriptions.forEach((sub) => {
1911
- if (sub.unsubscribe) sub.unsubscribe();
1912
- });
1913
- this._subscriptions.clear();
1914
- return { success: true };
1915
- }
1916
- // Start game
1917
- async startGame(gameConfig = {}, turnOrder = null) {
1918
- return roomsMock.startGame(this.roomId, gameConfig);
1919
- }
1920
- // End game
1921
- async endGame(winner = null, reason = null, gameResults = {}) {
1922
- return roomsMock.endGame(this.roomId, winner, reason, gameResults);
1923
- }
1924
- // Propose move (for client-proposed state architecture)
1925
- async proposeMove(proposalPayload) {
1926
- return roomsMock.proposeMove(this.roomId, proposalPayload);
1927
- }
1928
- // Validate move
1929
- async validateMove(moveId, isValid, reason = null, validatorId = null) {
1930
- console.log(`[Venus Mock VenusRoom] Validating move ${moveId}: ${isValid}`);
1931
- return { success: true, moveId, isValid, reason };
1932
- }
1933
- // Subscribe to game events
1934
- subscribeToGameEvents(callback) {
1935
- return roomsMock.subscribeToRoom(this.roomId, {
1936
- onOptimisticGameStateUpdated: callback,
1937
- onProposedMoveValidationUpdated: callback
1938
- });
1939
- }
1940
- // Generic message handler for room-manager.js integration
1941
- onMessage(callback) {
1942
- return roomsMock.subscribeToRoom(this.roomId, {
1943
- onRoomDataUpdated: callback,
1944
- onMessageReceived: callback,
1945
- onGameStarted: callback,
1946
- onTurnChanged: callback,
1947
- onOptimisticGameStateUpdated: callback,
1948
- onProposedMoveValidationUpdated: callback
1949
- });
1950
- }
1951
- // Unified subscription helper
1952
- subscribe(options = {}) {
1953
- const unsubFns = [];
1954
- if (options.onData) {
1955
- const sub = this.subscribeToData(options.onData);
1956
- unsubFns.push(() => sub.unsubscribe());
1957
- }
1958
- if (options.onMessages) {
1959
- const sub = this.subscribeToMessages(options.onMessages);
1960
- unsubFns.push(() => sub.unsubscribe());
1961
- }
1962
- if (options.onMoves || options.onGameEvents) {
1963
- const handler = options.onMoves || options.onGameEvents;
1964
- const sub = this.subscribeToGameEvents(handler);
1965
- unsubFns.push(() => sub.unsubscribe());
1966
- }
1967
- let called = false;
1968
- return () => {
1969
- if (called) return;
1970
- called = true;
1971
- unsubFns.forEach((fn) => {
1972
- try {
1973
- fn();
1974
- } catch (e) {
1975
- console.error("Mock room subscribe teardown error", e);
1976
- }
1977
- });
1978
- };
1979
- }
1980
- };
1981
- var roomsMock = {
1982
- createRoom(options = {}) {
1983
- try {
1984
- console.log(`[Venus Mock Rooms] Creating room with options:`, options);
1985
- const roomId = generateRoomId();
1986
- const creatorId = options.userId || "mock-user-creator";
1987
- const creatorDisplayName = options.userDisplayName || `Creator ${creatorId.slice(-4)}`;
1988
- const initialGameState = {
1989
- phase: "waiting",
1990
- currentPlayer: creatorId,
1991
- // Creator might be the first player by default
1992
- turnOrder: [creatorId],
1993
- playerStates: {
1994
- [creatorId]: {
1995
- displayName: creatorDisplayName,
1996
- status: "active",
1997
- role: "admin",
1998
- // Creator is admin
1999
- joinedAt: /* @__PURE__ */ new Date()
2000
- }
2001
- },
2002
- gameStartedAt: null,
2003
- turnCount: 0
2004
- // other game-specific state can be added by the H5 app via customMetadata or startGame
2005
- };
2006
- const room = {
2007
- id: roomId,
2008
- appId: options.appId || "mock-app",
2009
- name: options.name || "Mock Room",
2010
- type: "shared",
2011
- createdBy: creatorId,
2012
- createdAt: /* @__PURE__ */ new Date(),
2013
- updatedAt: /* @__PURE__ */ new Date(),
2014
- isPrivate: options.isPrivate || false,
2015
- maxPlayers: options.maxPlayers || 4,
2016
- currentPlayers: [creatorId],
2017
- status: "active",
2018
- customMetadata: {
2019
- ...options.customMetadata || {},
2020
- rules: {
2021
- ...options.customMetadata?.rules || {},
2022
- // Default generic rules, can be overridden by H5 app's options
2023
- ruleEngine: options.customMetadata?.rules?.ruleEngine || "generic-v1",
2024
- turnBased: options.customMetadata?.rules?.turnBased ?? true,
2025
- minPlayers: options.customMetadata?.rules?.minPlayers || 1,
2026
- maxPlayers: options.maxPlayers || 4,
2027
- gameState: initialGameState
2028
- }
2029
- },
2030
- admins: [creatorId],
2031
- roomCode: options.roomCode || (options.isPrivate ? generateRoomCode() : null),
2032
- description: options.description,
2033
- gameType: options.gameType,
2034
- data: {},
2035
- // General purpose data, game state is in customMetadata.rules.gameState
2036
- version: 1
2037
- };
2038
- mockRooms.set(roomId, room);
2039
- mockMessages.set(roomId, []);
2040
- mockRoomMoves.set(roomId, []);
2041
- console.log(`[Venus Mock Rooms] Created room ${roomId} with initial state:`, room);
2042
- return Promise.resolve(new MockVenusRoom(room));
2043
- } catch (error) {
2044
- console.error(`[Venus Mock Rooms] Error creating room:`, error);
2045
- return Promise.reject({ success: false, error: error.message || "Failed to create room" });
2046
- }
2047
- },
2048
- joinRoom(roomId, playerMetadata = {}) {
2049
- try {
2050
- console.log(`[Venus Mock Rooms] Joining room ${roomId}`);
2051
- const room = mockRooms.get(roomId);
2052
- if (!room) {
2053
- return Promise.reject({ success: false, error: "Room not found" });
2054
- }
2055
- const joiningPlayerId = playerMetadata.userId || "mock-user-" + Math.random().toString(36).substr(2, 5);
2056
- const joiningPlayerDisplayName = playerMetadata.displayName || `Player ${joiningPlayerId.slice(-4)}`;
2057
- if (room.currentPlayers.includes(joiningPlayerId)) {
2058
- console.log(`[Venus Mock Rooms] Player ${joiningPlayerId} already in room ${roomId}. Updating display name if needed.`);
2059
- if (room.customMetadata.rules.gameState.playerStates[joiningPlayerId]) {
2060
- room.customMetadata.rules.gameState.playerStates[joiningPlayerId].displayName = joiningPlayerDisplayName;
2061
- room.customMetadata.rules.gameState.playerStates[joiningPlayerId].status = "active";
2062
- } else {
2063
- room.customMetadata.rules.gameState.playerStates[joiningPlayerId] = {
2064
- displayName: joiningPlayerDisplayName,
2065
- status: "active",
2066
- role: "player",
2067
- joinedAt: /* @__PURE__ */ new Date()
2068
- };
2069
- }
2070
- room.updatedAt = /* @__PURE__ */ new Date();
2071
- room.version++;
2072
- broadcastEvent(roomId, "room_data_updated", { roomId, roomData: room, timestamp: Date.now() });
2073
- return Promise.resolve(new MockVenusRoom(room));
2074
- }
2075
- if (room.currentPlayers.length >= room.maxPlayers) {
2076
- return Promise.reject({ success: false, error: "Room is full" });
2077
- }
2078
- room.currentPlayers.push(joiningPlayerId);
2079
- room.customMetadata.rules.gameState.playerStates[joiningPlayerId] = {
2080
- displayName: joiningPlayerDisplayName,
2081
- status: "active",
2082
- role: "player",
2083
- joinedAt: /* @__PURE__ */ new Date()
2084
- };
2085
- if (room.customMetadata.rules.gameState.phase === "waiting" && room.customMetadata.rules.gameState.turnOrder) {
2086
- if (!room.customMetadata.rules.gameState.turnOrder.includes(joiningPlayerId)) {
2087
- room.customMetadata.rules.gameState.turnOrder.push(joiningPlayerId);
2088
- }
2089
- }
2090
- room.updatedAt = /* @__PURE__ */ new Date();
2091
- room.version++;
2092
- broadcastEvent(roomId, "player_joined", { roomId, player: { id: joiningPlayerId, displayName: joiningPlayerDisplayName } });
2093
- broadcastEvent(roomId, "room_data_updated", { roomId, roomData: room, timestamp: Date.now() });
2094
- console.log(`[Venus Mock Rooms] Player ${joiningPlayerId} joined room ${roomId}. Current state:`, room);
2095
- return Promise.resolve(new MockVenusRoom(room));
2096
- } catch (error) {
2097
- console.error(`[Venus Mock Rooms] Error joining room:`, error);
2098
- return Promise.reject({ success: false, error: error.message || "Failed to join room" });
2099
- }
2100
- },
2101
- updateRoomData(roomId, updates, merge = true) {
2102
- try {
2103
- console.log(`[Venus Mock Rooms] Updating room ${roomId} data:`, updates);
2104
- const room = mockRooms.get(roomId);
2105
- if (!room) {
2106
- throw new Error("Room not found");
2107
- }
2108
- if (merge) {
2109
- room.data = { ...room.data, ...updates };
2110
- } else {
2111
- room.data = updates;
2112
- }
2113
- room.updatedAt = /* @__PURE__ */ new Date();
2114
- room.version++;
2115
- broadcastEvent(roomId, "room_data_updated", {
2116
- roomId,
2117
- roomData: room,
2118
- timestamp: Date.now()
2119
- });
2120
- return Promise.resolve({
2121
- success: true
2122
- });
2123
- } catch (error) {
2124
- console.error(`[Venus Mock Rooms] Error updating room data:`, error);
2125
- return Promise.reject(new Error(error.message || "Failed to update room data"));
2126
- }
2127
- },
2128
- getRoomData(roomId) {
2129
- try {
2130
- console.log(`[Venus Mock Rooms] Getting room ${roomId} data`);
2131
- const room = mockRooms.get(roomId);
2132
- if (!room) {
2133
- throw new Error("Room not found");
2134
- }
2135
- return Promise.resolve({
2136
- success: true,
2137
- data: room.data || {}
2138
- });
2139
- } catch (error) {
2140
- console.error(`[Venus Mock Rooms] Error getting room data:`, error);
2141
- return Promise.reject(new Error(error.message || "Failed to get room data"));
2142
- }
2143
- },
2144
- sendMessage(roomId, message) {
2145
- try {
2146
- const room = mockRooms.get(roomId);
2147
- if (!room) {
2148
- return Promise.reject({ success: false, error: "Room not found" });
2149
- }
2150
- if (message.type === "chat") {
2151
- console.log(`[Venus Mock Rooms] Sending CHAT message to room ${roomId}:`, message);
2152
- const messageId = generateMessageId();
2153
- const messageData = {
2154
- id: messageId,
2155
- roomId,
2156
- senderId: message.senderId || "mock-user-chatter",
2157
- // H5 app should provide senderId
2158
- content: message.content || "",
2159
- type: "chat",
2160
- metadata: message.metadata || {},
2161
- timestamp: /* @__PURE__ */ new Date()
2162
- };
2163
- const messages = mockMessages.get(roomId) || [];
2164
- messages.push(messageData);
2165
- mockMessages.set(roomId, messages);
2166
- broadcastEvent(roomId, "message_received", { roomId, message: messageData });
2167
- return Promise.resolve({ success: true, messageId });
2168
- } else {
2169
- console.log(`[Venus Mock Rooms] Sending GAME ACTION/MOVE to room ${roomId} via moves subcollection:`, message);
2170
- const playerId = message.playerId || message.metadata?.playerId || "mock-player-action";
2171
- if (!playerId) ;
2172
- const move = {
2173
- playerId,
2174
- moveData: message.moveData || message.content || message.metadata || { type: message.type },
2175
- // Ensure type is captured
2176
- clientValidationHash: message.clientValidationHash,
2177
- timestamp: /* @__PURE__ */ new Date(),
2178
- // client-side timestamp for the move proposal
2179
- status: "pending_mock_processing"
2180
- };
2181
- const roomMoves = mockRoomMoves.get(roomId) || [];
2182
- roomMoves.push(move);
2183
- mockRoomMoves.set(roomId, roomMoves);
2184
- this._processMockMove(roomId, move, room);
2185
- return Promise.resolve({ success: true, moveId: "mock-move-" + Date.now() });
2186
- }
2187
- } catch (error) {
2188
- console.error(`[Venus Mock Rooms] Error sending message/move:`, error);
2189
- return Promise.reject({ success: false, error: error.message || "Failed to send message/move" });
2190
- }
2191
- },
2192
- subscribeToRoom(roomId, options = {}) {
2193
- try {
2194
- console.log(`[Venus Mock Rooms] Subscribing to room ${roomId}:`, options);
2195
- const room = mockRooms.get(roomId);
2196
- if (!room) {
2197
- throw new Error("Room not found");
2198
- }
2199
- const instanceId = "mock-instance-" + Date.now();
2200
- if (!mockSubscriptions.has(instanceId)) {
2201
- mockSubscriptions.set(instanceId, /* @__PURE__ */ new Map());
2202
- }
2203
- const subscriptions = mockSubscriptions.get(instanceId);
2204
- subscriptions.set(roomId, {
2205
- onRoomDataUpdated: options.onRoomDataUpdated,
2206
- onMessageReceived: options.onMessageReceived,
2207
- onPlayerJoined: options.onPlayerJoined,
2208
- onPlayerLeft: options.onPlayerLeft,
2209
- onGameStarted: options.onGameStarted,
2210
- onTurnChanged: options.onTurnChanged
2211
- });
2212
- return Promise.resolve({
2213
- success: true,
2214
- unsubscribe: () => {
2215
- subscriptions.delete(roomId);
2216
- console.log(`[Venus Mock Rooms] Unsubscribed from room ${roomId}`);
2217
- }
2218
- });
2219
- } catch (error) {
2220
- console.error(`[Venus Mock Rooms] Error subscribing to room:`, error);
2221
- return Promise.reject(new Error(error.message || "Failed to subscribe to room"));
2222
- }
2223
- },
2224
- listPublicRooms(gameType, limit = 20) {
2225
- try {
2226
- console.log(`[Venus Mock Rooms] Listing public rooms:`, { gameType, limit });
2227
- let rooms = Array.from(mockRooms.values()).filter(
2228
- (room) => !room.isPrivate && room.status === "active" && (!gameType || room.gameType === gameType)
2229
- );
2230
- rooms = rooms.slice(0, limit);
2231
- return Promise.resolve({
2232
- success: true,
2233
- rooms
2234
- });
2235
- } catch (error) {
2236
- console.error(`[Venus Mock Rooms] Error listing public rooms:`, error);
2237
- return Promise.reject(new Error(error.message || "Failed to list public rooms"));
2238
- }
2239
- },
2240
- searchRooms(searchQuery, gameType, limit = 20) {
2241
- try {
2242
- console.log(`[Venus Mock Rooms] Searching rooms:`, { searchQuery, gameType, limit });
2243
- let rooms = Array.from(mockRooms.values()).filter(
2244
- (room) => !room.isPrivate && room.status === "active" && (!gameType || room.gameType === gameType) && (!searchQuery || room.name.toLowerCase().includes(searchQuery.toLowerCase()) || room.description?.toLowerCase().includes(searchQuery.toLowerCase()))
2245
- );
2246
- rooms = rooms.slice(0, limit);
2247
- return Promise.resolve({
2248
- success: true,
2249
- rooms
2250
- });
2251
- } catch (error) {
2252
- console.error(`[Venus Mock Rooms] Error searching rooms:`, error);
2253
- return Promise.reject({ success: false, error: error.message || "Failed to search rooms" });
2254
- }
2255
- },
2256
- // Smart matchmaking - join existing room or create new one
2257
- joinOrCreateRoom(options = {}) {
2258
- try {
2259
- console.log(`[Venus Mock Rooms] Smart matchmaking with options:`, options);
2260
- const { matchCriteria = {}, createOptions = {} } = options;
2261
- let matchingRoom = null;
2262
- for (const room of mockRooms.values()) {
2263
- const matchesGameType = !matchCriteria.gameType || room.gameType === matchCriteria.gameType;
2264
- const matchesPrivacy = !matchCriteria.hasOwnProperty("isPrivate") || room.isPrivate === matchCriteria.isPrivate;
2265
- const hasSpace = !matchCriteria.hasSpace || room.currentPlayers.length < room.maxPlayers;
2266
- const isActive = room.status === "active";
2267
- const isWaiting = room.customMetadata?.rules?.gameState?.phase === "waiting";
2268
- if (matchesGameType && matchesPrivacy && hasSpace && isActive && isWaiting) {
2269
- matchingRoom = room;
2270
- console.log(`[Venus Mock Rooms] Found matching room: ${room.id}`);
2271
- break;
2272
- }
2273
- }
2274
- if (matchingRoom) {
2275
- console.log(`[Venus Mock Rooms] Joining existing room: ${matchingRoom.id}`);
2276
- const joiningPlayerId = createOptions.userId || options.userId || "mock-user-joiner";
2277
- const joiningPlayerDisplayName = createOptions.userDisplayName || options.userDisplayName || `Player ${joiningPlayerId.slice(-4)}`;
2278
- if (matchingRoom.currentPlayers.includes(joiningPlayerId)) {
2279
- return Promise.resolve({
2280
- action: "joined",
2281
- room: new MockVenusRoom(matchingRoom),
2282
- playersJoined: 0
2283
- });
2284
- }
2285
- matchingRoom.currentPlayers.push(joiningPlayerId);
2286
- matchingRoom.customMetadata.rules.gameState.playerStates[joiningPlayerId] = {
2287
- displayName: joiningPlayerDisplayName,
2288
- status: "active",
2289
- role: "player",
2290
- joinedAt: /* @__PURE__ */ new Date()
2291
- };
2292
- if (matchingRoom.customMetadata.rules.gameState.phase === "waiting" && matchingRoom.customMetadata.rules.gameState.turnOrder) {
2293
- if (!matchingRoom.customMetadata.rules.gameState.turnOrder.includes(joiningPlayerId)) {
2294
- matchingRoom.customMetadata.rules.gameState.turnOrder.push(joiningPlayerId);
2295
- }
2296
- }
2297
- matchingRoom.updatedAt = /* @__PURE__ */ new Date();
2298
- matchingRoom.version++;
2299
- if (matchingRoom.currentPlayers.length >= matchingRoom.maxPlayers) {
2300
- console.log(`[Venus Mock Rooms] Room ${matchingRoom.id} is full, auto-starting game`);
2301
- const gameState = matchingRoom.customMetadata.rules.gameState;
2302
- gameState.phase = "playing";
2303
- gameState.gameStartedAt = /* @__PURE__ */ new Date();
2304
- let turnOrder = [...matchingRoom.currentPlayers];
2305
- if (matchingRoom.customMetadata.rules.randomizePlayerOrder) {
2306
- for (let i = turnOrder.length - 1; i > 0; i--) {
2307
- const j = Math.floor(Math.random() * (i + 1));
2308
- [turnOrder[i], turnOrder[j]] = [turnOrder[j], turnOrder[i]];
2309
- }
2310
- }
2311
- gameState.turnOrder = turnOrder;
2312
- gameState.currentPlayer = turnOrder[0] || null;
2313
- if (matchingRoom.gameType === "chess" && turnOrder.length >= 2) {
2314
- gameState.playerStates[turnOrder[0]].gameRole = "white";
2315
- gameState.playerStates[turnOrder[1]].gameRole = "black";
2316
- }
2317
- broadcastEvent(matchingRoom.id, "game_started", {
2318
- roomId: matchingRoom.id,
2319
- gameState,
2320
- turnOrder: gameState.turnOrder,
2321
- currentPlayer: gameState.currentPlayer
2322
- });
2323
- }
2324
- broadcastEvent(matchingRoom.id, "player_joined", {
2325
- roomId: matchingRoom.id,
2326
- player: { id: joiningPlayerId, displayName: joiningPlayerDisplayName }
2327
- });
2328
- broadcastEvent(matchingRoom.id, "room_data_updated", {
2329
- roomId: matchingRoom.id,
2330
- roomData: matchingRoom,
2331
- timestamp: Date.now()
2332
- });
2333
- return Promise.resolve({
2334
- action: "joined",
2335
- room: new MockVenusRoom(matchingRoom),
2336
- playersJoined: 1
2337
- });
2338
- } else {
2339
- console.log(`[Venus Mock Rooms] No matching room found, creating new room`);
2340
- const roomCreationOptions = {
2341
- ...createOptions,
2342
- userId: createOptions.userId || options.userId || "mock-user-creator",
2343
- userDisplayName: createOptions.userDisplayName || options.userDisplayName || "Creator"
2344
- };
2345
- const createResult = this.createRoom(roomCreationOptions);
2346
- return createResult.then((room) => ({
2347
- action: "created",
2348
- room,
2349
- // createRoom already returns MockVenusRoom instance
2350
- playersJoined: 1
2351
- }));
2352
- }
2353
- } catch (error) {
2354
- console.error(`[Venus Mock Rooms] Error in joinOrCreateRoom:`, error);
2355
- return Promise.reject({ success: false, error: error.message || "Failed to join or create room" });
2356
- }
2357
- },
2358
- joinRoomByCode(roomCode, playerMetadata = {}) {
2359
- try {
2360
- console.log(`[Venus Mock Rooms] Joining room by code ${roomCode}`);
2361
- let foundRoom = null;
2362
- for (const [roomId, room] of mockRooms.entries()) {
2363
- if (room.roomCode === roomCode && room.status === "active") {
2364
- foundRoom = room;
2365
- break;
2366
- }
2367
- }
2368
- if (!foundRoom) {
2369
- return Promise.reject({ success: false, error: `Room not found with code: ${roomCode}` });
2370
- }
2371
- return this.joinRoom(foundRoom.id, playerMetadata);
2372
- } catch (error) {
2373
- console.error(`[Venus Mock Rooms] Error joining room by code:`, error);
2374
- return Promise.reject({ success: false, error: error.message || "Failed to join room by code" });
2375
- }
2376
- },
2377
- // Stage 2: Enhanced game features
2378
- startGame(roomId, gameConfig = {}, requestingUserId = "mock-admin-user") {
2379
- try {
2380
- console.log(`[Venus Mock Rooms] Starting game in room ${roomId} by ${requestingUserId}`);
2381
- const room = mockRooms.get(roomId);
2382
- if (!room) {
2383
- return Promise.reject({ success: false, error: "Room not found" });
2384
- }
2385
- if (!room.admins.includes(requestingUserId) && room.createdBy !== requestingUserId) {
2386
- return Promise.reject({ success: false, error: "Only admin or creator can start game" });
2387
- }
2388
- if (room.customMetadata.rules.gameState.phase === "playing") {
2389
- return Promise.reject({ success: false, error: "Game already in progress" });
2390
- }
2391
- const minPlayers = room.customMetadata.rules.minPlayers || 1;
2392
- if (room.currentPlayers.length < minPlayers) {
2393
- return Promise.reject({ success: false, error: `Not enough players. Needs ${minPlayers}` });
2394
- }
2395
- const gameState = room.customMetadata.rules.gameState;
2396
- gameState.phase = "playing";
2397
- gameState.gameStartedAt = /* @__PURE__ */ new Date();
2398
- let turnOrder = [...room.currentPlayers];
2399
- if (room.customMetadata.rules.randomizePlayerOrder) {
2400
- for (let i = turnOrder.length - 1; i > 0; i--) {
2401
- const j = Math.floor(Math.random() * (i + 1));
2402
- [turnOrder[i], turnOrder[j]] = [turnOrder[j], turnOrder[i]];
2403
- }
2404
- }
2405
- gameState.turnOrder = turnOrder;
2406
- gameState.currentPlayer = turnOrder[0] || null;
2407
- turnOrder.forEach((playerId) => {
2408
- if (!gameState.playerStates[playerId]) {
2409
- gameState.playerStates[playerId] = { displayName: `Player ${playerId.slice(-4)}`, status: "active", role: "player" };
2410
- } else {
2411
- gameState.playerStates[playerId].status = "active";
2412
- if (!gameState.playerStates[playerId].displayName) {
2413
- gameState.playerStates[playerId].displayName = `Player ${playerId.slice(-4)}`;
2414
- }
2415
- }
2416
- });
2417
- room.updatedAt = /* @__PURE__ */ new Date();
2418
- room.version++;
2419
- console.log(`[Venus Mock Rooms] Game started in room ${roomId}. New state:`, room);
2420
- broadcastEvent(roomId, "game_started", { roomId, gameState, turnOrder: gameState.turnOrder, currentPlayer: gameState.currentPlayer });
2421
- broadcastEvent(roomId, "room_data_updated", { roomId, roomData: room, timestamp: Date.now() });
2422
- return Promise.resolve({ success: true, ...room });
2423
- } catch (error) {
2424
- console.error(`[Venus Mock Rooms] Error starting game:`, error);
2425
- return Promise.reject({ success: false, error: error.message || "Failed to start game" });
2426
- }
2427
- },
2428
- endGame(roomId, winner = null, reason = null, gameResults = {}) {
2429
- try {
2430
- console.log(`[Venus Mock Rooms] Player requesting to end game in room ${roomId}`);
2431
- const room = mockRooms.get(roomId);
2432
- if (!room) return Promise.reject({ success: false, error: "Room not found" });
2433
- const playerId = gameResults.endedBy || "mock-player-ender";
2434
- const move = {
2435
- playerId,
2436
- moveData: {
2437
- type: "end_game",
2438
- winner,
2439
- reason,
2440
- gameResults
2441
- },
2442
- timestamp: /* @__PURE__ */ new Date(),
2443
- status: "pending_mock_processing"
2444
- };
2445
- const roomMoves = mockRoomMoves.get(roomId) || [];
2446
- roomMoves.push(move);
2447
- mockRoomMoves.set(roomId, roomMoves);
2448
- this._processMockMove(roomId, move, room);
2449
- return Promise.resolve({ success: true, moveId: "mock-move-" + Date.now() });
2450
- } catch (error) {
2451
- console.error(`[Venus Mock Rooms] Error ending game:`, error);
2452
- return Promise.reject({ success: false, error: error.message || "Failed to end game" });
2453
- }
2454
- },
2455
- // NEW: Propose move (client-proposed state architecture)
2456
- proposeMove(roomId, proposalPayload, proposerId = "mock-proposer") {
2457
- try {
2458
- console.log(`[Venus Mock Rooms] Player ${proposerId} proposing move in room ${roomId}:`, proposalPayload);
2459
- const room = mockRooms.get(roomId);
2460
- if (!room) return Promise.reject({ success: false, error: "Room not found" });
2461
- const proposedMoveId = `prop_move_${Date.now()}_${Math.random().toString(36).substr(2, 5)}`;
2462
- const proposedMove = {
2463
- id: proposedMoveId,
2464
- proposerProfileId: proposerId,
2465
- timestamp: /* @__PURE__ */ new Date(),
2466
- gameSpecificState: proposalPayload.gameSpecificState,
2467
- moveType: proposalPayload.moveType,
2468
- clientContext: proposalPayload.clientContext,
2469
- clientProposalId: proposalPayload.clientProposalId,
2470
- serverGenericValidationStatus: "pending",
2471
- serverCustomValidationStatus: "pending",
2472
- clientConsensusStatus: "pending",
2473
- ...proposalPayload.resignedBy && { resignedBy: proposalPayload.resignedBy },
2474
- ...proposalPayload.winner && { winner: proposalPayload.winner }
2475
- };
2476
- if (!mockRoomMoves.has(roomId + "_proposed")) {
2477
- mockRoomMoves.set(roomId + "_proposed", []);
2478
- }
2479
- mockRoomMoves.get(roomId + "_proposed").push(proposedMove);
2480
- if (proposalPayload.gameSpecificState) {
2481
- room.optimisticGameState = proposalPayload.gameSpecificState;
2482
- room.lastProposedMoveId = proposedMoveId;
2483
- room.lastProposedMoveBy = proposerId;
2484
- room.lastProposedMoveAt = /* @__PURE__ */ new Date();
2485
- room.updatedAt = /* @__PURE__ */ new Date();
2486
- room.version++;
2487
- }
2488
- setTimeout(() => {
2489
- this._processMockProposedMove(roomId, proposedMoveId, proposedMove, room);
2490
- }, 100);
2491
- broadcastEvent(roomId, "room_data_updated", {
2492
- roomId,
2493
- roomData: room,
2494
- timestamp: Date.now()
2495
- });
2496
- if (proposalPayload.gameSpecificState) {
2497
- broadcastEvent(roomId, "app:h5:optimisticGameStateUpdated", {
2498
- roomId,
2499
- optimisticGameState: proposalPayload.gameSpecificState
2500
- });
2501
- }
2502
- return Promise.resolve({
2503
- success: true,
2504
- proposedMoveId,
2505
- optimisticGameState: proposalPayload.gameSpecificState
2506
- });
2507
- } catch (error) {
2508
- console.error(`[Venus Mock Rooms] Error proposing move:`, error);
2509
- return Promise.reject({ success: false, error: error.message || "Failed to propose move" });
2510
- }
2511
- },
2512
- // NEW internal helper to simulate server-side move processing for mock API
2513
- _processMockMove(roomId, move, room) {
2514
- console.log("[Venus Mock Rooms] Simulating server processing for move:", move);
2515
- move.id = "processed-mock-move-" + Date.now();
2516
- setTimeout(() => {
2517
- const currentRoomState = mockRooms.get(roomId);
2518
- if (!currentRoomState) return;
2519
- const { rules, gameState } = currentRoomState.customMetadata;
2520
- const { playerId, moveData } = move;
2521
- let isValidMove = true;
2522
- let validationError = null;
2523
- if (rules.turnBased && gameState.currentPlayer !== playerId) {
2524
- isValidMove = false;
2525
- validationError = "Not current player's turn.";
2526
- console.warn(`[Venus Mock Rooms] Invalid move by ${playerId}: Not their turn. Current: ${gameState.currentPlayer}`);
2527
- }
2528
- const moveType = moveData?.type;
2529
- if (isValidMove && moveType && rules.allowedMessageTypes?.[gameState.phase]?.[moveType]) {
2530
- const ruleForMoveType = rules.allowedMessageTypes[gameState.phase][moveType];
2531
- if (ruleForMoveType.requiredFields) {
2532
- for (const field of ruleForMoveType.requiredFields) {
2533
- if (!(field in moveData)) {
2534
- isValidMove = false;
2535
- validationError = `Missing required field: ${field} for move type ${moveType}.`;
2536
- console.warn(`[Venus Mock Rooms] Invalid move by ${playerId}: ${validationError}`);
2537
- break;
2538
- }
2539
- }
2540
- }
2541
- } else if (isValidMove && moveType && !rules.allowedMessageTypes?.[gameState.phase]?.[moveType]) {
2542
- console.warn(`[Venus Mock Rooms] Move type "${moveType}" not defined in allowedMessageTypes for phase "${gameState.phase}". Processing by default.`);
2543
- }
2544
- if (isValidMove) {
2545
- console.log("[Venus Mock Rooms] Move considered valid by mock server. Updating game state.");
2546
- move.status = "mock_valid";
2547
- gameState.lastMoveBy = playerId;
2548
- gameState.lastMoveTimestamp = /* @__PURE__ */ new Date();
2549
- if (moveData.type === "end_game") {
2550
- gameState.phase = "ended";
2551
- gameState.endedAt = /* @__PURE__ */ new Date();
2552
- currentRoomState.status = "archived";
2553
- console.log("[Venus Mock Rooms] Mock: Game ended.");
2554
- } else if (moveData.type === "force_update_state") {
2555
- Object.assign(gameState, moveData.payload);
2556
- console.log("[Venus Mock Rooms] Mock: Game state forcibly updated with:", moveData.payload);
2557
- }
2558
- const nonTurnAdvancingMoves = ["end_game", "force_update_state"];
2559
- if (rules.turnBased && gameState.turnOrder && gameState.turnOrder.length > 0 && !nonTurnAdvancingMoves.includes(moveData.type)) {
2560
- const currentPlayerIndex = gameState.turnOrder.indexOf(gameState.currentPlayer || "");
2561
- if (currentPlayerIndex !== -1) {
2562
- const nextPlayerIndex = (currentPlayerIndex + 1) % gameState.turnOrder.length;
2563
- gameState.currentPlayer = gameState.turnOrder[nextPlayerIndex];
2564
- gameState.turnCount = (gameState.turnCount || 0) + 1;
2565
- console.log(`[Venus Mock Rooms] Mock: Turn advanced to ${gameState.currentPlayer}`);
2566
- broadcastEvent(roomId, "turn_changed", {
2567
- roomId,
2568
- currentPlayer: gameState.currentPlayer,
2569
- previousPlayer: playerId,
2570
- // The one who just moved
2571
- turnCount: gameState.turnCount
2572
- });
2573
- }
2574
- }
2575
- currentRoomState.updatedAt = /* @__PURE__ */ new Date();
2576
- currentRoomState.version++;
2577
- broadcastEvent(roomId, "room_data_updated", { roomId, roomData: currentRoomState, timestamp: Date.now() });
2578
- } else {
2579
- console.warn("[Venus Mock Rooms] Move considered invalid by mock server. No game state change.", { validationError });
2580
- move.status = "mock_invalid";
2581
- move.error = validationError;
2582
- }
2583
- console.log("[Venus Mock Rooms] Finished mock processing for move:", move);
2584
- }, 100);
2585
- },
2586
- // NEW: Process proposed move for mock API
2587
- _processMockProposedMove(roomId, proposedMoveId, proposedMove, room) {
2588
- console.log("[Venus Mock Rooms] Simulating server processing for proposed move:", proposedMoveId);
2589
- const { rules, gameState } = room.customMetadata;
2590
- const { proposerProfileId, gameSpecificState, moveType } = proposedMove;
2591
- let isGenericValid = true;
2592
- let genericValidationReason = "";
2593
- if (moveType === "resignation") {
2594
- const resignedBy = proposedMove.resignedBy || gameSpecificState?.resignedBy;
2595
- if (!resignedBy) {
2596
- isGenericValid = false;
2597
- genericValidationReason = "Security violation: Resignation move must specify who is resigning (resignedBy field required).";
2598
- } else if (resignedBy !== proposerProfileId) {
2599
- isGenericValid = false;
2600
- genericValidationReason = `Security violation: Player ${proposerProfileId} cannot resign on behalf of player ${resignedBy}. Players can only resign themselves.`;
2601
- } else if (!gameState.playerStates || !gameState.playerStates[proposerProfileId]) {
2602
- isGenericValid = false;
2603
- genericValidationReason = `Security violation: Player ${proposerProfileId} is not in this game and cannot resign.`;
2604
- } else {
2605
- console.log(`[Venus Mock Rooms] \u2705 Resignation move validated: ${proposerProfileId} is resigning themselves`);
2606
- }
2607
- } else {
2608
- if (rules.turnBased && gameState.currentPlayer !== proposerProfileId) {
2609
- isGenericValid = false;
2610
- genericValidationReason = `Not player's turn. Current: ${gameState.currentPlayer}`;
2611
- }
2612
- }
2613
- if (isGenericValid && moveType && rules.allowedMessageTypes?.[gameState.phase]?.[moveType]) {
2614
- const ruleForMoveType = rules.allowedMessageTypes[gameState.phase][moveType];
2615
- if (ruleForMoveType.requiredFields) {
2616
- for (const field of ruleForMoveType.requiredFields) {
2617
- const hasField = moveType === "resignation" ? proposedMove[field] !== void 0 || gameSpecificState[field] !== void 0 : gameSpecificState[field] !== void 0;
2618
- if (!hasField) {
2619
- isGenericValid = false;
2620
- genericValidationReason = `Missing required field: ${field}`;
2621
- break;
2622
- }
2623
- }
2624
- }
2625
- }
2626
- proposedMove.serverGenericValidationStatus = isGenericValid ? "valid" : "invalid";
2627
- proposedMove.serverGenericValidationReason = genericValidationReason;
2628
- proposedMove.serverCustomValidationStatus = "not_applicable";
2629
- proposedMove.clientConsensusStatus = "valid";
2630
- if (isGenericValid) {
2631
- Object.assign(gameState, gameSpecificState);
2632
- if (gameSpecificState.isGameOver === true) {
2633
- gameState.phase = "ended";
2634
- gameState.winner = gameSpecificState.winner || null;
2635
- gameState.endReason = gameSpecificState.gameStatus || "completed";
2636
- gameState.endedAt = /* @__PURE__ */ new Date();
2637
- gameState.currentPlayer = null;
2638
- console.log(`[Venus Mock Rooms] \u{1F3C1} Game ended in room ${roomId}: ${gameState.endReason}, winner: ${gameState.winner || "draw"}`);
2639
- } else {
2640
- if (rules.turnBased && gameState.turnOrder && gameState.turnOrder.length > 0) {
2641
- const currentPlayerIndex = gameState.turnOrder.indexOf(gameState.currentPlayer || "");
2642
- if (currentPlayerIndex !== -1) {
2643
- const nextPlayerIndex = (currentPlayerIndex + 1) % gameState.turnOrder.length;
2644
- gameState.currentPlayer = gameState.turnOrder[nextPlayerIndex];
2645
- gameState.turnCount = (gameState.turnCount || 0) + 1;
2646
- }
2647
- }
2011
+ this.rpcClient = rpcClient;
2012
+ }
2013
+ async requestChatCompletionAsync(request) {
2014
+ const response = await this.rpcClient.call(
2015
+ "H5_AI_CHAT_COMPLETION" /* AI_CHAT_COMPLETION */,
2016
+ {
2017
+ request: (() => {
2018
+ const { apiKey, ...requestWithoutApiKey } = request;
2019
+ return requestWithoutApiKey;
2020
+ })()
2648
2021
  }
2649
- gameState.lastMoveBy = proposerProfileId;
2650
- gameState.lastMoveTimestamp = /* @__PURE__ */ new Date();
2651
- room.updatedAt = /* @__PURE__ */ new Date();
2652
- room.version++;
2653
- console.log(`[Venus Mock Rooms] Proposed move ${proposedMoveId} validated and applied`);
2654
- } else {
2655
- console.log(`[Venus Mock Rooms] Proposed move ${proposedMoveId} validation failed: ${genericValidationReason}`);
2022
+ );
2023
+ return response;
2024
+ }
2025
+ async getAvailableCompletionModels() {
2026
+ const response = await this.rpcClient.call(
2027
+ "H5_AI_GET_AVAILABLE_MODELS" /* AI_GET_AVAILABLE_MODELS */
2028
+ );
2029
+ return response;
2030
+ }
2031
+ };
2032
+
2033
+ // src/ai/MockAiApi.ts
2034
+ var MockAiApi = class {
2035
+ async requestChatCompletionAsync(request) {
2036
+ const { apiKey, ...requestBody } = request;
2037
+ if (!apiKey) {
2038
+ throw new Error("An API key is required for a chat completion request when developing locally.");
2656
2039
  }
2657
- broadcastEvent(roomId, "app:h5:proposedMoveValidationUpdated", {
2658
- roomId,
2659
- proposedMoveId,
2660
- proposedMoveData: proposedMove
2040
+ const response = await fetch("https://series.ullm.rho.live/api/v1/completions", {
2041
+ method: "POST",
2042
+ headers: {
2043
+ "Content-Type": "application/json",
2044
+ "Authorization": `Bearer ${apiKey}`
2045
+ },
2046
+ body: JSON.stringify(requestBody)
2661
2047
  });
2662
- if (isGenericValid) {
2663
- broadcastEvent(roomId, "room_data_updated", {
2664
- roomId,
2665
- roomData: room,
2666
- timestamp: Date.now()
2667
- });
2668
- }
2669
- },
2670
- getUserRooms(appId, includeArchived = false) {
2671
- try {
2672
- console.log(`[Venus Mock Rooms] Getting user rooms:`, { appId, includeArchived });
2673
- const userId = "mock-user";
2674
- let rooms = Array.from(mockRooms.values()).filter(
2675
- (room) => room.currentPlayers.includes(userId) && (!appId || room.appId === appId) && (includeArchived || room.status === "active")
2676
- );
2677
- rooms.sort((a, b) => new Date(b.updatedAt) - new Date(a.updatedAt));
2678
- return Promise.resolve({
2679
- success: true,
2680
- rooms
2681
- });
2682
- } catch (error) {
2683
- console.error(`[Venus Mock Rooms] Error getting user rooms:`, error);
2684
- return Promise.reject(new Error(error.message || "Failed to get user rooms"));
2685
- }
2686
- },
2687
- getGameState(roomId) {
2688
- try {
2689
- console.log(`[Venus Mock Rooms] Getting game state for room ${roomId}`);
2690
- const room = mockRooms.get(roomId);
2691
- if (!room) {
2692
- return Promise.reject({ success: false, error: "Room not found" });
2693
- }
2694
- const gameState = room.customMetadata?.rules?.gameState || {};
2695
- return Promise.resolve({
2696
- success: true,
2697
- data: gameState
2698
- // Return the authoritative game state from the mock room
2699
- });
2700
- } catch (error) {
2701
- console.error(`[Venus Mock Rooms] Error getting game state:`, error);
2702
- return Promise.reject({ success: false, error: error.message || "Failed to get game state" });
2048
+ if (!response.ok) {
2049
+ throw new Error(`HTTP error! status: ${response.status}`);
2703
2050
  }
2051
+ const data = await response.json();
2052
+ return data;
2704
2053
  }
2705
- };
2706
- function initializeRooms(venusApiInstance, mockData = null) {
2707
- if (mockData && Array.isArray(mockData.rooms)) {
2708
- mockData.rooms.forEach((room) => {
2709
- mockRooms.set(room.id, room);
2710
- mockMessages.set(room.id, []);
2711
- mockPlayers.set(room.id, room.currentPlayers.map((playerId) => ({
2712
- id: playerId,
2713
- roomId: room.id,
2714
- joinedAt: /* @__PURE__ */ new Date(),
2715
- lastActive: /* @__PURE__ */ new Date(),
2716
- status: "active",
2717
- customData: {},
2718
- role: playerId === room.createdBy ? "owner" : "member"
2719
- })));
2054
+ async getAvailableCompletionModels() {
2055
+ const response = await fetch("https://series.ullm.rho.live/api/v1/models", {
2056
+ method: "GET",
2057
+ headers: {
2058
+ "Content-Type": "application/json"
2059
+ }
2720
2060
  });
2061
+ if (!response.ok) {
2062
+ throw new Error(`HTTP error! status: ${response.status}`);
2063
+ }
2064
+ const data = await response.json();
2065
+ return data;
2721
2066
  }
2722
- venusApiInstance.rooms = createProxiedObject.call(venusApiInstance, "rooms", roomsMock);
2723
- venusApiInstance.getUserRooms = createProxiedMethod("getUserRooms", roomsMock.getUserRooms);
2724
- venusApiInstance.createRoom = createProxiedMethod("createRoom", roomsMock.createRoom);
2725
- venusApiInstance.joinRoom = createProxiedMethod("joinRoom", roomsMock.joinRoom);
2726
- venusApiInstance.joinOrCreateRoom = createProxiedMethod("joinOrCreateRoom", roomsMock.joinOrCreateRoom);
2727
- venusApiInstance.joinRoomByCode = createProxiedMethod("joinRoomByCode", roomsMock.joinRoomByCode);
2728
- venusApiInstance.listPublicRooms = createProxiedMethod("listPublicRooms", roomsMock.listPublicRooms);
2729
- venusApiInstance.searchRooms = createProxiedMethod("searchRooms", roomsMock.searchRooms);
2730
- venusApiInstance.subscribeToRoom = createProxiedMethod("subscribeToRoom", roomsMock.subscribeToRoom);
2731
- venusApiInstance.isRoomSystemEnabled = function() {
2732
- return true;
2733
- };
2067
+ };
2068
+
2069
+ // src/ai/index.ts
2070
+ function initializeAi(venusApi, host) {
2071
+ venusApi.ai = host.ai;
2734
2072
  }
2735
2073
 
2736
2074
  // src/venus-api/systems/asset-loader.js
@@ -4638,17 +3976,22 @@ function initializeIap(venusApiInstance, host) {
4638
3976
  // src/profile/HostProfileApi.ts
4639
3977
  var HostProfileApi = class {
4640
3978
  getCurrentProfile() {
4641
- if (window.venus._config && window.venus._config.profile) {
4642
- return {
4643
- id: window.venus._config.profile.id || "unknown",
4644
- name: window.venus._config.profile.username || "Unknown User",
4645
- username: window.venus._config.profile.username || "unknown"
4646
- };
3979
+ const profile = window.venus?.profile;
3980
+ if (!profile) {
3981
+ throw new Error(
3982
+ "[Venus SDK] Host profile handshake did not complete. Await VenusAPI.initializeAsync() so INIT_SDK can deliver the profile before calling profile APIs."
3983
+ );
3984
+ }
3985
+ if (!profile.id || !profile.username) {
3986
+ throw new Error(
3987
+ "[Venus SDK] INIT_SDK returned an incomplete profile (missing id/username). The host must supply real credentials before rooms APIs are used."
3988
+ );
4647
3989
  }
4648
3990
  return {
4649
- id: "mock_profile_123",
4650
- name: "Mock User",
4651
- username: "mockuser"
3991
+ id: profile.id,
3992
+ username: profile.username,
3993
+ avatarUrl: profile.avatarUrl,
3994
+ isAnonymous: profile.isAnonymous
4652
3995
  };
4653
3996
  }
4654
3997
  };
@@ -4659,7 +4002,8 @@ var MockProfileApi = class {
4659
4002
  return {
4660
4003
  id: "mock_profile_123",
4661
4004
  name: "Mock User",
4662
- username: "mockuser"
4005
+ username: "mockuser",
4006
+ isAnonymous: false
4663
4007
  };
4664
4008
  }
4665
4009
  };
@@ -6072,41 +5416,8 @@ function initializeSimulation(venusApi, host) {
6072
5416
  };
6073
5417
  }
6074
5418
 
6075
- // src/rooms/MockRoomsApi.ts
6076
- var MockRoomsApi = class {
6077
- constructor() {
6078
- // Mock room storage to simulate real-time rooms in development
6079
- __publicField(this, "mockRooms", /* @__PURE__ */ new Map());
6080
- __publicField(this, "mockMessages", /* @__PURE__ */ new Map());
6081
- // roomId -> messages[]
6082
- __publicField(this, "mockRoomMoves", /* @__PURE__ */ new Map());
6083
- // roomId -> moves[]
6084
- __publicField(this, "mockSubscriptions", /* @__PURE__ */ new Map());
6085
- }
6086
- join(roomId) {
6087
- throw new Error("Method not implemented.");
6088
- }
6089
- // instanceId -> subscriptions
6090
- createRoom(options) {
6091
- return Promise.resolve(void 0);
6092
- }
6093
- generateRoomId() {
6094
- return "room_" + Date.now() + "_" + Math.random().toString(36).substr(2, 9);
6095
- }
6096
- // Helper to generate message IDs
6097
- generateMessageId() {
6098
- return "msg_" + Date.now() + "_" + Math.random().toString(36).substr(2, 9);
6099
- }
6100
- // Helper to generate room codes
6101
- generateRoomCode() {
6102
- const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
6103
- let code = "";
6104
- for (let i = 0; i < 6; i++) {
6105
- code += characters.charAt(Math.floor(Math.random() * characters.length));
6106
- }
6107
- return code;
6108
- }
6109
- };
5419
+ // src/MockHost.ts
5420
+ init_rooms();
6110
5421
 
6111
5422
  // src/logging/MockLoggingApi.ts
6112
5423
  var MockLoggingApi = class {
@@ -6252,7 +5563,90 @@ var MockSharedAssetsApi = class {
6252
5563
  }
6253
5564
  };
6254
5565
 
5566
+ // src/game-preloader/MockPreloaderApi.ts
5567
+ var MockPreloaderApi = class {
5568
+ async showLoadScreen() {
5569
+ console.log("showLoadScreen");
5570
+ }
5571
+ async hideLoadScreen() {
5572
+ console.log("hideLoadScreen");
5573
+ }
5574
+ async setLoaderText(text) {
5575
+ console.log("setLoaderText", text);
5576
+ }
5577
+ async setLoaderProgress(progress) {
5578
+ console.log("setLoaderProgress", progress);
5579
+ }
5580
+ };
5581
+
5582
+ // src/game-preloader/RpcPreloaderApi.ts
5583
+ var RpcPreloaderApi = class {
5584
+ constructor(rpcClient) {
5585
+ __publicField(this, "rpcClient");
5586
+ this.rpcClient = rpcClient;
5587
+ }
5588
+ async showLoadScreen() {
5589
+ await this.rpcClient.call("H5_SHOW_LOAD_SCREEN" /* H5_SHOW_LOAD_SCREEN */);
5590
+ }
5591
+ async hideLoadScreen() {
5592
+ await this.rpcClient.call("H5_HIDE_LOAD_SCREEN" /* H5_HIDE_LOAD_SCREEN */);
5593
+ }
5594
+ async setLoaderText(text) {
5595
+ await this.rpcClient.call("H5_SET_LOADER_TEXT" /* H5_SET_LOADER_TEXT */, { text });
5596
+ }
5597
+ async setLoaderProgress(progress) {
5598
+ await this.rpcClient.call("H5_SET_LOADER_PROGRESS" /* H5_SET_LOADER_PROGRESS */, { progress });
5599
+ }
5600
+ };
5601
+
5602
+ // src/game-preloader/index.ts
5603
+ function initializePreloader(venusApi, host) {
5604
+ venusApi.preloader = host.preloader;
5605
+ }
5606
+
6255
5607
  // src/MockHost.ts
5608
+ var ROOMS_UNAVAILABLE_MESSAGE = "[Venus SDK] Rooms API is only available when running inside the Venus host environment.";
5609
+ function createUnavailableRoomsApi() {
5610
+ const roomsUnavailableError = () => new Error(ROOMS_UNAVAILABLE_MESSAGE);
5611
+ return {
5612
+ async createRoom() {
5613
+ throw roomsUnavailableError();
5614
+ },
5615
+ async joinOrCreateRoom() {
5616
+ throw roomsUnavailableError();
5617
+ },
5618
+ async getUserRooms() {
5619
+ throw roomsUnavailableError();
5620
+ },
5621
+ async joinRoomByCode() {
5622
+ throw roomsUnavailableError();
5623
+ },
5624
+ subscribe() {
5625
+ throw roomsUnavailableError();
5626
+ },
5627
+ async updateData() {
5628
+ throw roomsUnavailableError();
5629
+ },
5630
+ async getData() {
5631
+ throw roomsUnavailableError();
5632
+ },
5633
+ async sendMessage() {
5634
+ throw roomsUnavailableError();
5635
+ },
5636
+ async leave() {
5637
+ throw roomsUnavailableError();
5638
+ },
5639
+ async startGame() {
5640
+ throw roomsUnavailableError();
5641
+ },
5642
+ async proposeMove() {
5643
+ throw roomsUnavailableError();
5644
+ },
5645
+ async validateMove() {
5646
+ throw roomsUnavailableError();
5647
+ }
5648
+ };
5649
+ }
6256
5650
  var MockHost = class {
6257
5651
  constructor(venusApi) {
6258
5652
  __publicField(this, "ads");
@@ -6276,6 +5670,7 @@ var MockHost = class {
6276
5670
  __publicField(this, "rooms");
6277
5671
  __publicField(this, "logging");
6278
5672
  __publicField(this, "iap");
5673
+ __publicField(this, "preloader");
6279
5674
  __publicField(this, "state", 0 /* PLAYING */);
6280
5675
  __publicField(this, "venusApi");
6281
5676
  __publicField(this, "_isInitialized", false);
@@ -6305,18 +5700,19 @@ var MockHost = class {
6305
5700
  this.features = new MockFeaturesApi();
6306
5701
  this.lifecycle = this._mockLifecyclesApi;
6307
5702
  this.simulation = new MockSimulationApi();
6308
- this.rooms = new MockRoomsApi();
5703
+ this.rooms = createUnavailableRoomsApi();
6309
5704
  this.logging = new MockLoggingApi();
6310
5705
  this.iap = new MockIapApi();
5706
+ initializeRoomsApi(this.venusApi, this);
5707
+ this.preloader = new MockPreloaderApi();
6311
5708
  venusApi.isMock = () => true;
6312
5709
  this.venusApi.sharedAssets = new MockSharedAssetsApi(this.venusApi);
6313
5710
  }
6314
5711
  get isInitialized() {
6315
5712
  return this._isInitialized;
6316
5713
  }
6317
- initialize() {
5714
+ async initialize(options = {}) {
6318
5715
  this._isInitialized = true;
6319
- return Promise.resolve();
6320
5716
  }
6321
5717
  updateUiControls() {
6322
5718
  const controls = {
@@ -7044,177 +6440,49 @@ var VenusTransport = class {
7044
6440
  }
7045
6441
  };
7046
6442
 
7047
- // src/notifications/RpcNotificationsApi.ts
7048
- var RpcNotificationsApi = class {
6443
+ // src/RemoteHost.ts
6444
+ init_rooms();
6445
+
6446
+ // src/rooms/RpcRoomsApi.ts
6447
+ init_VenusRoom();
6448
+ var RpcRoomsApi = class {
7049
6449
  constructor(rpcClient) {
7050
6450
  __publicField(this, "rpcClient");
6451
+ __publicField(this, "subscriptions");
6452
+ __publicField(this, "transportSubscription", null);
7051
6453
  this.rpcClient = rpcClient;
7052
- }
7053
- async scheduleLocalNotification(title, body, options) {
7054
- const request = {
7055
- title,
7056
- body,
7057
- data: options?.payload,
7058
- key: options?.groupId,
7059
- priority: options?.priority || 1,
7060
- trigger: options?.trigger ?? null
6454
+ this.subscriptions = {
6455
+ data: {},
6456
+ messages: {},
6457
+ gameEvents: {},
6458
+ allEvents: {}
7061
6459
  };
7062
- const response = await this.rpcClient.call(
7063
- "H5_SCHEDULE_LOCAL_NOTIFICATION" /* SCHEDULE_LOCAL_NOTIFICATION */,
7064
- request
7065
- );
7066
- if (response.scheduled) {
7067
- return response.id;
7068
- }
7069
- return null;
7070
- }
7071
- async cancelLocalNotification(id) {
7072
- const result = await this.rpcClient.call(
7073
- "H5_CANCEL_LOCAL_NOTIFICATION" /* CANCEL_LOCAL_NOTIFICATION */,
7074
- {
7075
- id
7076
- }
7077
- );
7078
- return result.canceled;
7079
- }
7080
- async getAllScheduledLocalNotifications() {
7081
- const response = await this.rpcClient.call(
7082
- "H5_GET_ALL_SCHEDULED_LOCAL_NOTIFICATIONS" /* GET_ALL_SCHEDULED_LOCAL_NOTIFICATIONS */,
7083
- {}
7084
- );
7085
- const notifications = response.notifications.map((notif) => {
7086
- return {
7087
- id: notif.identifier,
7088
- title: notif.content.title,
7089
- body: notif.content.body,
7090
- payload: notif.content.data,
7091
- trigger: notif.trigger
7092
- };
7093
- });
7094
- return notifications;
7095
6460
  }
7096
- async isLocalNotificationsEnabled() {
7097
- const response = await this.rpcClient.call(
7098
- "H5_IS_LOCAL_NOTIFICATIONS_ENABLED" /* IS_LOCAL_NOTIFICATIONS_ENABLED */,
7099
- {}
7100
- );
7101
- return response.enabled;
6461
+ /**
6462
+ * Get the subscription state for external access (used by setupRoomNotifications)
6463
+ */
6464
+ getSubscriptions() {
6465
+ return this.subscriptions;
7102
6466
  }
7103
- async setLocalNotificationsEnabled(enabled) {
7104
- const response = await this.rpcClient.call(
7105
- "H5_SET_LOCAL_NOTIFICATIONS_ENABLED" /* SET_LOCAL_NOTIFICATIONS_ENABLED */,
7106
- {
7107
- enabled
7108
- }
6467
+ /**
6468
+ * Set up room notification routing from the transport
6469
+ */
6470
+ setupNotifications(transport) {
6471
+ const { setupRoomNotifications: setupRoomNotifications2 } = (init_rooms(), __toCommonJS(rooms_exports));
6472
+ this.transportSubscription = setupRoomNotifications2(
6473
+ transport,
6474
+ () => this.getSubscriptions()
7109
6475
  );
7110
- return response.enabled;
7111
- }
7112
- };
7113
-
7114
- // src/rooms/VenusRoom.ts
7115
- var VenusRoom = class {
7116
- constructor(roomData) {
7117
- __publicField(this, "id");
7118
- __publicField(this, "name");
7119
- __publicField(this, "players");
7120
- __publicField(this, "maxPlayers");
7121
- __publicField(this, "gameType");
7122
- __publicField(this, "appId");
7123
- __publicField(this, "type");
7124
- __publicField(this, "createdBy");
7125
- __publicField(this, "createdAt");
7126
- __publicField(this, "updatedAt");
7127
- __publicField(this, "isPrivate");
7128
- __publicField(this, "currentPlayers");
7129
- __publicField(this, "status");
7130
- __publicField(this, "customMetadata");
7131
- __publicField(this, "admins");
7132
- __publicField(this, "roomCode");
7133
- __publicField(this, "description");
7134
- __publicField(this, "data");
7135
- __publicField(this, "version");
7136
- __publicField(this, "_subscriptions", /* @__PURE__ */ new Map());
7137
- this.id = roomData.id;
7138
- this.name = roomData.name;
7139
- this.players = roomData.currentPlayers || [];
7140
- this.maxPlayers = roomData.maxPlayers;
7141
- this.gameType = roomData.gameType;
7142
- this.appId = roomData.appId;
7143
- this.type = roomData.type;
7144
- this.createdBy = roomData.createdBy;
7145
- this.createdAt = roomData.createdAt;
7146
- this.updatedAt = roomData.updatedAt;
7147
- this.isPrivate = roomData.isPrivate;
7148
- this.currentPlayers = roomData.currentPlayers || [];
7149
- this.status = roomData.status;
7150
- this.customMetadata = roomData.customMetadata || {};
7151
- this.admins = roomData.admins || [];
7152
- this.roomCode = roomData.roomCode;
7153
- this.description = roomData.description;
7154
- this.data = roomData.data || {};
7155
- this.version = roomData.version;
7156
- console.log(`VenusRoom: Created room object for ${this.id}`, {
7157
- hasCustomMetadata: !!this.customMetadata,
7158
- hasGameState: !!this.customMetadata?.rules?.gameState,
7159
- gamePhase: this.customMetadata?.rules?.gameState?.phase,
7160
- currentPlayer: this.customMetadata?.rules?.gameState?.currentPlayer
7161
- });
7162
- }
7163
- updateFromRoomData(newRoomData) {
7164
- if (newRoomData.id === this.id) {
7165
- this.name = newRoomData.name || this.name;
7166
- this.players = newRoomData.currentPlayers || this.players;
7167
- this.maxPlayers = newRoomData.maxPlayers || this.maxPlayers;
7168
- this.gameType = newRoomData.gameType || this.gameType;
7169
- this.currentPlayers = newRoomData.currentPlayers || this.currentPlayers;
7170
- this.customMetadata = newRoomData.customMetadata || this.customMetadata;
7171
- this.data = newRoomData.data || this.data;
7172
- this.status = newRoomData.status || this.status;
7173
- this.updatedAt = newRoomData.updatedAt || this.updatedAt;
7174
- console.log(`VenusRoom: Updated room object ${this.id} with fresh data`, {
7175
- hasCustomMetadata: !!this.customMetadata,
7176
- hasGameState: !!this.customMetadata?.rules?.gameState,
7177
- gamePhase: this.customMetadata?.rules?.gameState?.phase,
7178
- currentPlayer: this.customMetadata?.rules?.gameState?.currentPlayer
7179
- });
7180
- }
7181
6476
  }
7182
- // NEW: Generic message handler for room-manager.js integration
7183
- onMessage(callback) {
7184
- const subscriptionId = "messages_" + Date.now() + "_" + Math.random().toString(36).substr(2, 9);
7185
- if (!window.venus._roomSubscriptions.allEvents) {
7186
- window.venus._roomSubscriptions.allEvents = {};
7187
- }
7188
- if (!window.venus._roomSubscriptions.allEvents[this.id]) {
7189
- window.venus._roomSubscriptions.allEvents[this.id] = [];
6477
+ /**
6478
+ * Clean up subscriptions and resources
6479
+ */
6480
+ dispose() {
6481
+ if (this.transportSubscription) {
6482
+ this.transportSubscription.unsubscribe();
6483
+ this.transportSubscription = null;
6484
+ console.log("[Venus Rooms] Cleaned up room notification subscription");
7190
6485
  }
7191
- window.venus._roomSubscriptions.allEvents[this.id].push(callback);
7192
- this._subscriptions.set(subscriptionId, {
7193
- type: "allEvents",
7194
- callback
7195
- });
7196
- return {
7197
- unsubscribe: () => {
7198
- const callbacks = window.venus._roomSubscriptions.allEvents[this.id] || [];
7199
- const index = callbacks.indexOf(callback);
7200
- if (index > -1) callbacks.splice(index, 1);
7201
- this._subscriptions.delete(subscriptionId);
7202
- }
7203
- };
7204
- }
7205
- };
7206
-
7207
- // src/rooms/RpcRoomsApi.ts
7208
- var RpcRoomsApi = class {
7209
- constructor(rpcClient) {
7210
- __publicField(this, "rpcClient");
7211
- __publicField(this, "isRoomSystemEnabled", function() {
7212
- return true;
7213
- });
7214
- this.rpcClient = rpcClient;
7215
- }
7216
- join(roomId) {
7217
- throw new Error("Method not implemented.");
7218
6486
  }
7219
6487
  async createRoom(options) {
7220
6488
  const response = await this.rpcClient.call(
@@ -7248,33 +6516,6 @@ var RpcRoomsApi = class {
7248
6516
  playersJoined: data.playersJoined
7249
6517
  };
7250
6518
  }
7251
- async listPublicRooms(gameType, limit = 20) {
7252
- const response = await this.rpcClient.call(
7253
- "H5_ROOM_LIST_PUBLIC" /* H5_ROOM_LIST_PUBLIC */,
7254
- {
7255
- gameType,
7256
- limit
7257
- }
7258
- );
7259
- if (!response.success) {
7260
- throw new Error(response.error || "Failed to list public rooms");
7261
- }
7262
- return response.rooms || [];
7263
- }
7264
- async searchRooms(searchQuery, gameType, limit = 20) {
7265
- const response = await this.rpcClient.call(
7266
- "H5_ROOM_SEARCH" /* H5_ROOM_SEARCH */,
7267
- {
7268
- searchQuery,
7269
- gameType,
7270
- limit
7271
- }
7272
- );
7273
- if (!response.success) {
7274
- throw new Error(response.error || "Failed to search rooms");
7275
- }
7276
- return response.rooms || [];
7277
- }
7278
6519
  async joinRoomByCode(roomCode) {
7279
6520
  const response = await this.rpcClient.call(
7280
6521
  "H5_ROOM_JOIN_BY_CODE" /* H5_ROOM_JOIN_BY_CODE */,
@@ -7282,7 +6523,7 @@ var RpcRoomsApi = class {
7282
6523
  roomCode
7283
6524
  }
7284
6525
  );
7285
- if (!response.success) {
6526
+ if (response?.success === false) {
7286
6527
  throw new Error(response.error || "Failed to join room by code");
7287
6528
  }
7288
6529
  const roomData = response.roomData || response;
@@ -7290,15 +6531,14 @@ var RpcRoomsApi = class {
7290
6531
  return room;
7291
6532
  }
7292
6533
  // Get user's rooms with optional filtering
7293
- async getUserRooms(appId, includeArchived = false) {
6534
+ async getUserRooms(includeArchived = false) {
7294
6535
  const response = await this.rpcClient.call(
7295
6536
  "H5_ROOM_GET_USER_ROOMS" /* H5_ROOM_GET_USER_ROOMS */,
7296
6537
  {
7297
- appId,
7298
- includePersonal: includeArchived
6538
+ includeArchived
7299
6539
  }
7300
6540
  );
7301
- if (!response.success) {
6541
+ if (response?.success === false) {
7302
6542
  throw new Error(response.error || "Failed to get user rooms");
7303
6543
  }
7304
6544
  const rawRooms = response.rooms || [];
@@ -7321,62 +6561,6 @@ var RpcRoomsApi = class {
7321
6561
  }
7322
6562
  return venusRooms;
7323
6563
  }
7324
- // Convenience method for common use case
7325
- quickMatch(gameType) {
7326
- return this.joinOrCreateRoom({
7327
- matchCriteria: {
7328
- gameType,
7329
- isPrivate: false,
7330
- hasSpace: true
7331
- },
7332
- createOptions: {
7333
- name: gameType + " Game",
7334
- gameType,
7335
- isPrivate: false,
7336
- maxPlayers: 4
7337
- // sensible default
7338
- }
7339
- });
7340
- }
7341
- // Enhanced room creation with game rules
7342
- async createGameRoom(options) {
7343
- const enhancedOptions = {
7344
- ...options,
7345
- customMetadata: {
7346
- ...options.customMetadata,
7347
- rules: {
7348
- ruleEngine: options.ruleEngine || "basic",
7349
- validateMessages: options.validateMessages || false,
7350
- randomizePlayerOrder: options.randomizePlayerOrder || false,
7351
- clientValidation: options.clientValidation || false,
7352
- allowedMessageTypes: options.allowedMessageTypes || {},
7353
- gameState: {
7354
- phase: "waiting",
7355
- currentPlayer: null,
7356
- turnOrder: [],
7357
- playerStates: {},
7358
- ...options.initialGameState
7359
- },
7360
- ...options.rules
7361
- }
7362
- }
7363
- };
7364
- return this.createRoom(enhancedOptions);
7365
- }
7366
- // Convenience method for subscribing to all game events
7367
- subscribeToGameEvents(roomId, callback) {
7368
- if (!window.venus._roomSubscriptions.gameEvents[roomId]) {
7369
- window.venus._roomSubscriptions.gameEvents[roomId] = [];
7370
- }
7371
- window.venus._roomSubscriptions.gameEvents[roomId].push(callback);
7372
- return {
7373
- unsubscribe: () => {
7374
- const callbacks = window.venus._roomSubscriptions.gameEvents[roomId] || [];
7375
- const index = callbacks.indexOf(callback);
7376
- if (index > -1) callbacks.splice(index, 1);
7377
- }
7378
- };
7379
- }
7380
6564
  async updateData(room, updates, merge = true) {
7381
6565
  const response = await this.rpcClient.call(
7382
6566
  "H5_ROOM_UPDATE_DATA" /* H5_ROOM_UPDATE_DATA */,
@@ -7386,7 +6570,7 @@ var RpcRoomsApi = class {
7386
6570
  merge
7387
6571
  }
7388
6572
  );
7389
- if (!response.success) {
6573
+ if (response?.success === false) {
7390
6574
  throw new Error(response.error || "Failed to update room data");
7391
6575
  }
7392
6576
  return response.data;
@@ -7398,7 +6582,7 @@ var RpcRoomsApi = class {
7398
6582
  roomId: room.id
7399
6583
  }
7400
6584
  );
7401
- if (!response.success) {
6585
+ if (response?.success === false) {
7402
6586
  throw new Error(response.error || "Failed to get room data");
7403
6587
  }
7404
6588
  return response.data;
@@ -7411,7 +6595,7 @@ var RpcRoomsApi = class {
7411
6595
  message: messageData
7412
6596
  }
7413
6597
  );
7414
- if (!response.success) {
6598
+ if (response?.success === false) {
7415
6599
  throw new Error(response.error || "Failed to send message");
7416
6600
  }
7417
6601
  return response.messageId;
@@ -7423,7 +6607,7 @@ var RpcRoomsApi = class {
7423
6607
  roomId: room.id
7424
6608
  }
7425
6609
  );
7426
- if (!response.success) {
6610
+ if (response?.success === false) {
7427
6611
  throw new Error(response.error || "Failed to leave room");
7428
6612
  }
7429
6613
  return response;
@@ -7437,7 +6621,7 @@ var RpcRoomsApi = class {
7437
6621
  turnOrder
7438
6622
  }
7439
6623
  );
7440
- if (!response.success) {
6624
+ if (response?.success === false) {
7441
6625
  throw new Error(response.error || "Failed to start game");
7442
6626
  }
7443
6627
  return response.data;
@@ -7453,7 +6637,7 @@ var RpcRoomsApi = class {
7453
6637
  clientProposalId: proposalPayload.clientProposalId
7454
6638
  }
7455
6639
  );
7456
- if (!response.success) {
6640
+ if (response?.success === false) {
7457
6641
  throw new Error(response.error || "Failed to propose move");
7458
6642
  }
7459
6643
  return response.data;
@@ -7464,20 +6648,20 @@ var RpcRoomsApi = class {
7464
6648
  }
7465
6649
  async roomSubscribeToGameEvents(room, callback) {
7466
6650
  "game_" + Date.now() + "_" + Math.random().toString(36).substr(2, 9);
7467
- if (!window.venus._roomSubscriptions.gameEvents[room.id]) {
7468
- window.venus._roomSubscriptions.gameEvents[room.id] = [];
6651
+ if (!this.subscriptions.gameEvents[room.id]) {
6652
+ this.subscriptions.gameEvents[room.id] = [];
7469
6653
  }
7470
- window.venus._roomSubscriptions.gameEvents[room.id].push(callback);
6654
+ this.subscriptions.gameEvents[room.id].push(callback);
7471
6655
  }
7472
6656
  subscribe(room, options = {}) {
7473
6657
  const subscriptionIds = [];
7474
6658
  const roomId = room.id;
7475
6659
  if (options.onData) {
7476
6660
  const dataSubId = "data_" + Date.now() + "_" + Math.random().toString(36).substr(2, 9);
7477
- if (!window.venus._roomSubscriptions.data[roomId]) {
7478
- window.venus._roomSubscriptions.data[roomId] = [];
6661
+ if (!this.subscriptions.data[roomId]) {
6662
+ this.subscriptions.data[roomId] = [];
7479
6663
  }
7480
- window.venus._roomSubscriptions.data[roomId].push(options.onData);
6664
+ this.subscriptions.data[roomId].push(options.onData);
7481
6665
  subscriptionIds.push({
7482
6666
  type: "data",
7483
6667
  id: dataSubId,
@@ -7486,10 +6670,10 @@ var RpcRoomsApi = class {
7486
6670
  }
7487
6671
  if (options.onMessages) {
7488
6672
  const msgSubId = "messages_" + Date.now() + "_" + Math.random().toString(36).substr(2, 9);
7489
- if (!window.venus._roomSubscriptions.messages[roomId]) {
7490
- window.venus._roomSubscriptions.messages[roomId] = [];
6673
+ if (!this.subscriptions.messages[roomId]) {
6674
+ this.subscriptions.messages[roomId] = [];
7491
6675
  }
7492
- window.venus._roomSubscriptions.messages[roomId].push(options.onMessages);
6676
+ this.subscriptions.messages[roomId].push(options.onMessages);
7493
6677
  subscriptionIds.push({
7494
6678
  type: "messages",
7495
6679
  id: msgSubId,
@@ -7498,18 +6682,20 @@ var RpcRoomsApi = class {
7498
6682
  }
7499
6683
  if (options.onMoves || options.onGameEvents) {
7500
6684
  const handler = options.onMoves || options.onGameEvents;
7501
- const gameSubId = "game_" + Date.now() + "_" + Math.random().toString(36).substr(2, 9);
7502
- if (!window.venus._roomSubscriptions.gameEvents[roomId]) {
7503
- window.venus._roomSubscriptions.gameEvents[roomId] = [];
6685
+ if (handler) {
6686
+ const gameSubId = "game_" + Date.now() + "_" + Math.random().toString(36).substr(2, 9);
6687
+ if (!this.subscriptions.gameEvents[roomId]) {
6688
+ this.subscriptions.gameEvents[roomId] = [];
6689
+ }
6690
+ this.subscriptions.gameEvents[roomId].push(handler);
6691
+ subscriptionIds.push({
6692
+ type: "gameEvents",
6693
+ id: gameSubId,
6694
+ callback: handler
6695
+ });
7504
6696
  }
7505
- window.venus._roomSubscriptions.gameEvents[roomId].push(handler);
7506
- subscriptionIds.push({
7507
- type: "gameEvents",
7508
- id: gameSubId,
7509
- callback: handler
7510
- });
7511
6697
  }
7512
- const needsSubscription = subscriptionIds.length > 0 && (!window.venus._roomSubscriptions.data[roomId] || window.venus._roomSubscriptions.data[roomId].length <= 1) && (!window.venus._roomSubscriptions.messages[roomId] || window.venus._roomSubscriptions.messages[roomId].length <= 1) && (!window.venus._roomSubscriptions.gameEvents[roomId] || window.venus._roomSubscriptions.gameEvents[roomId].length <= 1);
6698
+ 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;
7513
6699
  if (needsSubscription) {
7514
6700
  this.rpcClient.call("H5_ROOM_SUBSCRIBE" /* H5_ROOM_SUBSCRIBE */, {
7515
6701
  roomId,
@@ -7525,11 +6711,12 @@ var RpcRoomsApi = class {
7525
6711
  if (called) return;
7526
6712
  called = true;
7527
6713
  subscriptionIds.forEach((sub) => {
7528
- const callbacks = window.venus._roomSubscriptions[sub.type][roomId] || [];
6714
+ const bucket = this.subscriptions[sub.type];
6715
+ const callbacks = bucket && bucket[roomId] || [];
7529
6716
  const index = callbacks.indexOf(sub.callback);
7530
6717
  if (index > -1) callbacks.splice(index, 1);
7531
6718
  });
7532
- const hasNoCallbacks = (!window.venus._roomSubscriptions.data[roomId] || window.venus._roomSubscriptions.data[roomId].length === 0) && (!window.venus._roomSubscriptions.messages[roomId] || window.venus._roomSubscriptions.messages[roomId].length === 0) && (!window.venus._roomSubscriptions.gameEvents[roomId] || window.venus._roomSubscriptions.gameEvents[roomId].length === 0);
6719
+ const hasNoCallbacks = (this.subscriptions.data[roomId]?.length ?? 0) === 0 && (this.subscriptions.messages[roomId]?.length ?? 0) === 0 && (this.subscriptions.gameEvents[roomId]?.length ?? 0) === 0;
7533
6720
  if (hasNoCallbacks) {
7534
6721
  this.rpcClient.call("H5_ROOM_UNSUBSCRIBE" /* H5_ROOM_UNSUBSCRIBE */, {
7535
6722
  roomId
@@ -7568,6 +6755,7 @@ var RemoteHost = class {
7568
6755
  __publicField(this, "rooms");
7569
6756
  __publicField(this, "logging");
7570
6757
  __publicField(this, "iap");
6758
+ __publicField(this, "preloader");
7571
6759
  __publicField(this, "venusApi");
7572
6760
  __publicField(this, "rpcClient");
7573
6761
  __publicField(this, "_isInitialized", false);
@@ -7622,18 +6810,22 @@ var RemoteHost = class {
7622
6810
  this.rooms = new RpcRoomsApi(rpcClient);
7623
6811
  this.logging = new RpcLoggingApi(this, rpcClient);
7624
6812
  this.iap = new RpcIapApi(rpcClient);
6813
+ this.preloader = new RpcPreloaderApi(rpcClient);
7625
6814
  venusApi.isMock = () => false;
7626
6815
  this.venusApi.sharedAssets = new RpcSharedAssetsApi(rpcClient, venusApi);
6816
+ initializeRoomsApi(this.venusApi, this);
7627
6817
  console.log("[Venus SDK] Remote host created");
7628
6818
  }
7629
6819
  get isInitialized() {
7630
6820
  return this._isInitialized;
7631
6821
  }
7632
- async initialize() {
6822
+ async initialize(options = {}) {
7633
6823
  this.log("Initializing Remote Host...");
7634
6824
  const transport = new VenusTransport();
7635
6825
  transport.start();
7636
6826
  this.rpcClient.start(transport);
6827
+ const roomsApi = this.rooms;
6828
+ roomsApi.setupNotifications(transport);
7637
6829
  try {
7638
6830
  this.log("Trying to initialize using NEW method...");
7639
6831
  transport.instanceId = await this.initNew();
@@ -7693,6 +6885,26 @@ var RemoteHost = class {
7693
6885
  {},
7694
6886
  1e3
7695
6887
  );
6888
+ if (response.profile) {
6889
+ const profile = response.profile;
6890
+ const sanitizedProfile = {
6891
+ id: profile.id,
6892
+ username: profile.username,
6893
+ avatarUrl: profile.avatarUrl ?? null,
6894
+ isAnonymous: Boolean(profile.isAnonymous)
6895
+ };
6896
+ if (typeof window !== "undefined") {
6897
+ const globalWindow = window;
6898
+ const venus = globalWindow.venus || (globalWindow.venus = {});
6899
+ venus.profile = sanitizedProfile;
6900
+ if (venus._config) {
6901
+ venus._config.profile = sanitizedProfile;
6902
+ }
6903
+ if (venus.config) {
6904
+ venus.config.profile = sanitizedProfile;
6905
+ }
6906
+ }
6907
+ }
7696
6908
  return response.instanceId;
7697
6909
  }
7698
6910
  async initOld(transport) {
@@ -7730,8 +6942,11 @@ function createHost(venusApi, isMock) {
7730
6942
  }
7731
6943
  }
7732
6944
 
6945
+ // src/venus-api/index.js
6946
+ init_rooms();
6947
+
7733
6948
  // src/version.ts
7734
- var SDK_VERSION = "2.4.1";
6949
+ var SDK_VERSION = "2.6.2";
7735
6950
 
7736
6951
  // src/venus-api/index.js
7737
6952
  var HapticStyle = {
@@ -7848,12 +7063,7 @@ var VenusAPI2 = class {
7848
7063
  // Static locale data at top level
7849
7064
  locale: "en-US",
7850
7065
  languageCode: "en",
7851
- // Static profile data (renamed from currentProfile)
7852
- profile: {
7853
- id: "mock-profile-123",
7854
- username: "MockProfile",
7855
- avatarUrl: "https://i.pravatar.cc/150?u=mock"
7856
- },
7066
+ // Note: Profile is now separate from config and accessed via getCurrentProfile()
7857
7067
  // Complete environment info (matching buildStaticConfig)
7858
7068
  environment: {
7859
7069
  isDevelopment: true,
@@ -7923,11 +7133,7 @@ var VenusAPI2 = class {
7923
7133
  this.config = createProxiedObject.call(this, "config", {
7924
7134
  locale: "en-US",
7925
7135
  languageCode: "en",
7926
- profile: {
7927
- id: "mock-user-123",
7928
- username: "Test User",
7929
- avatarUrl: null
7930
- },
7136
+ // Note: Profile is no longer in config - use getCurrentProfile() instead
7931
7137
  environment: {
7932
7138
  isDevelopment: true,
7933
7139
  platform: typeof navigator !== "undefined" ? navigator.platform : "unknown",
@@ -8041,12 +7247,14 @@ var VenusAPI2 = class {
8041
7247
  const host = createHost(this, !isInsideHostedEnv);
8042
7248
  this.host = host;
8043
7249
  initializeStorage(this, host);
7250
+ initializeRoomsApi(this, host);
8044
7251
  initializeAds(this, host);
8045
7252
  initializeTheme(this);
8046
7253
  initializePopups(this, host);
8047
7254
  initializeAnalytics(this, host);
8048
7255
  initializeIap(this, host);
8049
7256
  initializeLocalNotifications(this, host);
7257
+ initializePreloader(this, host);
8050
7258
  initializeTime(this, host);
8051
7259
  initializeLifecycleApi(this, host);
8052
7260
  initializeHaptics(this, host);
@@ -8061,7 +7269,6 @@ var VenusAPI2 = class {
8061
7269
  initializeStackNavigation(this, host);
8062
7270
  initializePost(this, host);
8063
7271
  initializeAi(this, host);
8064
- initializeRooms(this);
8065
7272
  initializeSimulation(this, host);
8066
7273
  initializeAssetLoader(this, createProxiedMethod);
8067
7274
  }
@@ -8117,7 +7324,9 @@ var VenusAPI2 = class {
8117
7324
  this.config.languageCode = this._mock.localeOverride.split("-")[0];
8118
7325
  }
8119
7326
  if (this._mock.roomsData) {
8120
- initializeRooms(this, this._mock.roomsData);
7327
+ console.warn(
7328
+ "[Venus Mock] Rooms mock data is no longer supported. Rooms functionality requires the Venus host environment."
7329
+ );
8121
7330
  }
8122
7331
  }
8123
7332
  //---------------------------------------
@@ -8137,7 +7346,8 @@ var VenusAPI2 = class {
8137
7346
  "hardDisableMock",
8138
7347
  "mock",
8139
7348
  "helpText",
8140
- "forceRemoteCdn"
7349
+ "forceRemoteCdn",
7350
+ "usePreloader"
8141
7351
  ];
8142
7352
  const supportedMockParams = [
8143
7353
  "initDelay",
@@ -8178,7 +7388,10 @@ var VenusAPI2 = class {
8178
7388
  );
8179
7389
  }
8180
7390
  }
8181
- await this.host.initialize();
7391
+ await this.host.initialize(options);
7392
+ if (!options.usePreloader) {
7393
+ await this.host.preloader.hideLoadScreen();
7394
+ }
8182
7395
  if (this._bootstrap.isInsideHostedEnvironment) {
8183
7396
  this._shared.initialized = true;
8184
7397
  resolve(true);