@ughuuu/game_server 1.0.382 → 1.0.791
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +174 -24
- package/dist/ApiClient.js +2 -2
- package/dist/api/AchievementsApi.js +224 -0
- package/dist/api/AdminAchievementsApi.js +356 -0
- package/dist/api/AdminChatApi.js +2 -2
- package/dist/api/AdminGroupsApi.js +2 -2
- package/dist/api/AdminKVApi.js +2 -2
- package/dist/api/AdminLeaderboardsApi.js +2 -2
- package/dist/api/AdminLobbiesApi.js +2 -2
- package/dist/api/AdminNotificationsApi.js +2 -2
- package/dist/api/AdminSessionsApi.js +2 -2
- package/dist/api/AdminUsersApi.js +2 -2
- package/dist/api/AuthenticationApi.js +2 -2
- package/dist/api/ChatApi.js +141 -12
- package/dist/api/FriendsApi.js +2 -2
- package/dist/api/GroupsApi.js +69 -27
- package/dist/api/HealthApi.js +2 -2
- package/dist/api/HooksApi.js +2 -2
- package/dist/api/KVApi.js +2 -2
- package/dist/api/LeaderboardsApi.js +43 -2
- package/dist/api/LobbiesApi.js +44 -2
- package/dist/api/NotificationsApi.js +2 -2
- package/dist/api/PartiesApi.js +206 -22
- package/dist/api/UsersApi.js +2 -2
- package/dist/index.js +157 -10
- package/dist/model/AcceptPartyInviteRequest.js +109 -0
- package/dist/model/AdminCreateAchievementRequest.js +182 -0
- package/dist/model/AdminCreateKvEntry200Response.js +2 -2
- package/dist/model/AdminCreateKvEntryRequest.js +2 -2
- package/dist/model/AdminCreateLeaderboardRequest.js +2 -2
- package/dist/model/AdminCreateNotification400Response.js +2 -2
- package/dist/model/AdminCreateNotificationRequest.js +2 -2
- package/dist/model/AdminDeleteChatConversation200Response.js +2 -2
- package/dist/model/AdminEndLeaderboard200Response.js +2 -2
- package/dist/model/AdminEndLeaderboard200ResponseData.js +2 -2
- package/dist/model/AdminIncrementAchievementRequest.js +130 -0
- package/dist/model/AdminListAchievements200Response.js +118 -0
- package/dist/model/AdminListChatMessages200Response.js +2 -2
- package/dist/model/AdminListChatMessages200ResponseDataInner.js +20 -3
- package/dist/model/AdminListGroups200Response.js +2 -2
- package/dist/model/AdminListKvEntries200Response.js +2 -2
- package/dist/model/AdminListKvEntries200ResponseDataInner.js +2 -2
- package/dist/model/AdminListLobbies200Response.js +2 -2
- package/dist/model/AdminListLobbies200ResponseDataInner.js +32 -2
- package/dist/model/AdminListNotifications200Response.js +2 -2
- package/dist/model/AdminListNotifications200ResponseDataInner.js +15 -2
- package/dist/model/AdminListNotifications200ResponseMeta.js +2 -2
- package/dist/model/AdminListSessions200Response.js +2 -2
- package/dist/model/AdminListSessions200ResponseDataInner.js +2 -2
- package/dist/model/AdminRevokeAchievementRequest.js +118 -0
- package/dist/model/AdminSubmitLeaderboardScore200Response.js +2 -2
- package/dist/model/AdminSubmitLeaderboardScore200ResponseData.js +14 -2
- package/dist/model/AdminSubmitLeaderboardScoreRequest.js +20 -8
- package/dist/model/AdminUnlockAchievementRequest.js +122 -0
- package/dist/model/AdminUpdateAchievement200Response.js +181 -0
- package/dist/model/AdminUpdateAchievementRequest.js +145 -0
- package/dist/model/AdminUpdateGroup200Response.js +23 -2
- package/dist/model/AdminUpdateGroupRequest.js +11 -2
- package/dist/model/AdminUpdateKvEntryRequest.js +2 -2
- package/dist/model/AdminUpdateLeaderboardRecordRequest.js +2 -2
- package/dist/model/AdminUpdateLeaderboardRequest.js +2 -2
- package/dist/model/AdminUpdateLobby200Response.js +2 -2
- package/dist/model/AdminUpdateLobbyRequest.js +11 -2
- package/dist/model/AdminUpdateUser200Response.js +2 -2
- package/dist/model/AdminUpdateUser200ResponseData.js +2 -2
- package/dist/model/AdminUpdateUserRequest.js +2 -2
- package/dist/model/CallHook200Response.js +2 -2
- package/dist/model/CallHookRequest.js +2 -2
- package/dist/model/CancelGroupInvite200Response.js +2 -2
- package/dist/model/CancelJoinRequest200Response.js +2 -2
- package/dist/model/CancelPartyInviteRequest.js +109 -0
- package/dist/model/ChatUnreadCount200Response.js +2 -2
- package/dist/model/CreateFriendRequestRequest.js +2 -2
- package/dist/model/CreateGroupRequest.js +11 -2
- package/dist/model/CreateLobbyRequest.js +11 -2
- package/dist/model/CreatePartyRequest.js +2 -2
- package/dist/model/DeclinePartyInviteRequest.js +109 -0
- package/dist/model/DeleteNotifications200Response.js +2 -2
- package/dist/model/DeleteNotificationsRequest.js +2 -2
- package/dist/model/DemoteGroupMemberRequest.js +2 -2
- package/dist/model/DeviceLoginRequest.js +2 -2
- package/dist/model/ErrorResponse.js +2 -2
- package/dist/model/GetChatMessage200Response.js +196 -0
- package/dist/model/GetCurrentUser200Response.js +2 -2
- package/dist/model/GetCurrentUser200ResponseLinkedProviders.js +2 -2
- package/dist/model/GetKv200Response.js +2 -2
- package/dist/model/GetLobby200Response.js +133 -0
- package/dist/model/GetLobby200ResponseMembersInner.js +146 -0
- package/dist/model/GetMyRecord200Response.js +2 -2
- package/dist/model/HealthResponse.js +2 -2
- package/dist/model/InviteToGroup200Response.js +90 -0
- package/dist/model/InviteToGroupRequest.js +2 -2
- package/dist/model/InviteToPartyRequest.js +109 -0
- package/dist/model/KickGroupMemberRequest.js +2 -2
- package/dist/model/KickUserRequest.js +2 -2
- package/dist/model/LinkDeviceRequest.js +2 -2
- package/dist/model/ListBlockedFriends200Response.js +2 -2
- package/dist/model/ListBlockedFriends200ResponseDataInner.js +2 -2
- package/dist/model/ListBlockedFriends200ResponseDataInnerRequester.js +2 -2
- package/dist/model/ListChatMessages200Response.js +6 -6
- package/dist/model/ListFriendRequests200Response.js +2 -2
- package/dist/model/ListFriendRequests200ResponseIncomingInner.js +2 -2
- package/dist/model/ListFriendRequests200ResponseIncomingInnerRequester.js +11 -2
- package/dist/model/ListFriendRequests200ResponseMeta.js +2 -2
- package/dist/model/ListFriends200Response.js +2 -2
- package/dist/model/ListFriends200ResponseDataInner.js +11 -2
- package/dist/model/ListGroupInvitations200Response.js +2 -2
- package/dist/model/ListGroupInvitations200ResponseDataInner.js +48 -3
- package/dist/model/ListGroupMembers200Response.js +2 -2
- package/dist/model/ListGroupMembers200ResponseDataInner.js +2 -2
- package/dist/model/ListJoinRequests200Response.js +2 -2
- package/dist/model/ListLeaderboardRecords200Response.js +2 -2
- package/dist/model/ListLeaderboardRecords200ResponseDataInner.js +4 -4
- package/dist/model/ListLeaderboards200Response.js +2 -2
- package/dist/model/ListLeaderboards200ResponseDataInner.js +2 -2
- package/dist/model/ListLobbies200Response.js +2 -2
- package/dist/model/ListLobbies200ResponseDataInner.js +24 -2
- package/dist/model/ListMyGroups200Response.js +2 -2
- package/dist/model/ListMyGroups200ResponseDataInner.js +24 -2
- package/dist/model/ListNotifications200Response.js +2 -2
- package/dist/model/ListNotifications200ResponseDataInner.js +15 -2
- package/dist/model/ListPartyInvitations200ResponseInner.js +155 -0
- package/dist/model/ListRecordsAroundUser200Response.js +2 -2
- package/dist/model/ListSentInvitations200Response.js +2 -2
- package/dist/model/ListSentInvitations200ResponseDataInner.js +26 -2
- package/dist/model/Login200Response.js +2 -2
- package/dist/model/Login200ResponseData.js +15 -2
- package/dist/model/LoginRequest.js +2 -2
- package/dist/model/MarkChatReadRequest.js +8 -3
- package/dist/model/NotifyGroup200Response.js +2 -2
- package/dist/model/NotifyGroupRequest.js +3 -3
- package/dist/model/OAuthSessionData.js +15 -2
- package/dist/model/OAuthSessionDataDetails.js +2 -2
- package/dist/model/OAuthSessionStatus.js +2 -2
- package/dist/model/OauthApiCallback200Response.js +2 -2
- package/dist/model/OauthApiCallbackRequest.js +2 -2
- package/dist/model/OauthCallbackApiAppleIosRequest.js +2 -2
- package/dist/model/OauthGoogleIdTokenRequest.js +2 -2
- package/dist/model/OauthRequest200Response.js +2 -2
- package/dist/model/OauthSessionStatus404Response.js +2 -2
- package/dist/model/PartyCreateLobbyRequest.js +2 -2
- package/dist/model/PartyJoinLobbyRequest.js +2 -2
- package/dist/model/PromoteGroupMemberRequest.js +2 -2
- package/dist/model/QuickJoinRequest.js +2 -2
- package/dist/model/RefreshToken200Response.js +2 -2
- package/dist/model/RefreshToken200ResponseData.js +15 -2
- package/dist/model/RefreshTokenRequest.js +2 -2
- package/dist/model/ResolveLeaderboardSlugs200Response.js +89 -0
- package/dist/model/ResolveLeaderboardSlugsRequest.js +113 -0
- package/dist/model/SearchUsers200Response.js +2 -2
- package/dist/model/SearchUsers200ResponseDataInner.js +11 -2
- package/dist/model/SendChatMessageRequest.js +10 -5
- package/dist/model/SendNotificationRequest.js +2 -2
- package/dist/model/ShowParty200Response.js +13 -13
- package/dist/model/ShowParty200ResponseMembersInner.js +11 -2
- package/dist/model/UpdateChatMessageRequest.js +99 -0
- package/dist/model/UpdateCurrentUserDisplayNameRequest.js +2 -2
- package/dist/model/UpdateCurrentUserPassword400Response.js +2 -2
- package/dist/model/UpdateCurrentUserPasswordRequest.js +2 -2
- package/dist/model/UpdateGroupRequest.js +11 -2
- package/dist/model/UpdateLobbyRequest.js +11 -2
- package/dist/model/UpdatePartyRequest.js +2 -2
- package/dist/model/UserAchievements200Response.js +124 -0
- package/dist/model/UserAchievements200ResponseDataInner.js +192 -0
- package/dist/realtime.js +247 -0
- package/dist/webrtc.js +375 -0
- package/package.json +16 -23
- package/dist/model/CreateLobby401Response.js +0 -89
- package/dist/model/JoinLobby200Response.js +0 -89
- package/dist/model/JoinLobbyRequest.js +0 -90
- package/dist/model/JoinPartyByCodeRequest.js +0 -113
- package/dist/model/KickUser200Response.js +0 -89
- package/dist/model/LeaveLobby200Response.js +0 -89
- package/dist/model/ListChatMessages200ResponseDataInner.js +0 -170
- package/dist/model/ListLeaderboardRecords200ResponseMeta.js +0 -125
- package/dist/model/ListLobbies200ResponseInner.js +0 -153
- package/dist/model/ListLobbies200ResponseMeta.js +0 -125
- package/dist/model/Login200ResponseDataUser.js +0 -97
- package/dist/model/RemoveFriendship401Response.js +0 -89
package/dist/realtime.js
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports["default"] = exports.GameRealtime = void 0;
|
|
7
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
8
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
9
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
10
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
11
|
+
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
|
|
12
|
+
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
|
|
13
|
+
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
|
|
14
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
15
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
16
|
+
/**
|
|
17
|
+
* GameRealtime — Phoenix WebSocket client for game_server.
|
|
18
|
+
*
|
|
19
|
+
* Wraps Phoenix.Socket to provide helpers for common game_server channel topics.
|
|
20
|
+
* Requires the `phoenix` npm package (peer dependency).
|
|
21
|
+
*
|
|
22
|
+
* Usage (browser / Node.js with bundler):
|
|
23
|
+
*
|
|
24
|
+
* import { GameRealtime } from '@ughuuu/game_server'
|
|
25
|
+
*
|
|
26
|
+
* const realtime = new GameRealtime('https://your-server.com', accessToken)
|
|
27
|
+
*
|
|
28
|
+
* // Join the authenticated user channel
|
|
29
|
+
* const userChannel = realtime.joinUserChannel(userId)
|
|
30
|
+
* userChannel.on('notification', (payload) => console.log('notification:', payload))
|
|
31
|
+
* userChannel.on('updated', (payload) => console.log('user updated:', payload))
|
|
32
|
+
*
|
|
33
|
+
* // Join a lobby channel
|
|
34
|
+
* const lobbyChannel = realtime.joinLobbyChannel(lobbyId)
|
|
35
|
+
* lobbyChannel.on('updated', (payload) => console.log('lobby event:', payload))
|
|
36
|
+
*
|
|
37
|
+
* realtime.disconnect()
|
|
38
|
+
*
|
|
39
|
+
* Peer dependency:
|
|
40
|
+
*
|
|
41
|
+
* npm install phoenix
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
var _Socket = null;
|
|
45
|
+
try {
|
|
46
|
+
// Works in Node (bundled) and browser environments
|
|
47
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
48
|
+
_Socket = require('phoenix').Socket;
|
|
49
|
+
} catch (_) {
|
|
50
|
+
// Swallow — will throw a descriptive error at instantiation time
|
|
51
|
+
}
|
|
52
|
+
var GameRealtime = exports.GameRealtime = /*#__PURE__*/function () {
|
|
53
|
+
/**
|
|
54
|
+
* @param {string} serverUrl - Base HTTP(S) or WS(S) server URL,
|
|
55
|
+
* e.g. "https://game.example.com" or "wss://game.example.com"
|
|
56
|
+
* @param {string} token - JWT access token from the REST login endpoints
|
|
57
|
+
* @param {Object} socketOpts - Optional Phoenix.Socket constructor options
|
|
58
|
+
*/
|
|
59
|
+
function GameRealtime(serverUrl, token) {
|
|
60
|
+
var socketOpts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
61
|
+
_classCallCheck(this, GameRealtime);
|
|
62
|
+
if (!_Socket) {
|
|
63
|
+
throw new Error('GameRealtime requires the "phoenix" npm package. Install it: npm install phoenix');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Normalise URL: strip trailing slash, ensure ws(s):// scheme, append /socket
|
|
67
|
+
var wsUrl = serverUrl.replace(/\/$/, '').replace(/^http(s?):\/\//, function (_m, s) {
|
|
68
|
+
return "ws".concat(s, "://");
|
|
69
|
+
}) + '/socket';
|
|
70
|
+
this._token = token;
|
|
71
|
+
this._socket = new _Socket(wsUrl, _objectSpread({
|
|
72
|
+
params: {
|
|
73
|
+
token: token
|
|
74
|
+
}
|
|
75
|
+
}, socketOpts));
|
|
76
|
+
this._socket.connect();
|
|
77
|
+
/** @type {Map<string, Object>} topic → Phoenix Channel */
|
|
78
|
+
this._channels = new Map();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ── Channel helpers ──────────────────────────────────────────────────────
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Join the user channel for notifications, presence, and real-time events.
|
|
85
|
+
* Topic: `"user:<userId>"`
|
|
86
|
+
* @param {string|number} userId
|
|
87
|
+
* @param {Object} params - Extra join params merged with the auth token
|
|
88
|
+
* @returns {Object} Phoenix Channel
|
|
89
|
+
*/
|
|
90
|
+
return _createClass(GameRealtime, [{
|
|
91
|
+
key: "joinUserChannel",
|
|
92
|
+
value: function joinUserChannel(userId) {
|
|
93
|
+
var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
94
|
+
return this._join("user:".concat(userId), params);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Join a lobby channel for in-lobby events (member joins/leaves, updates).
|
|
99
|
+
* Topic: `"lobby:<lobbyId>"`
|
|
100
|
+
* @param {string|number} lobbyId
|
|
101
|
+
* @param {Object} params
|
|
102
|
+
* @returns {Object} Phoenix Channel
|
|
103
|
+
*/
|
|
104
|
+
}, {
|
|
105
|
+
key: "joinLobbyChannel",
|
|
106
|
+
value: function joinLobbyChannel(lobbyId) {
|
|
107
|
+
var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
108
|
+
return this._join("lobby:".concat(lobbyId), params);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Join the global lobbies feed (lobby list changes).
|
|
113
|
+
* Topic: `"lobbies"`
|
|
114
|
+
* @param {Object} params
|
|
115
|
+
* @returns {Object} Phoenix Channel
|
|
116
|
+
*/
|
|
117
|
+
}, {
|
|
118
|
+
key: "joinLobbiesChannel",
|
|
119
|
+
value: function joinLobbiesChannel() {
|
|
120
|
+
var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
121
|
+
return this._join('lobbies', params);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Join a group channel for group events.
|
|
126
|
+
* Topic: `"group:<groupId>"`
|
|
127
|
+
* @param {string|number} groupId
|
|
128
|
+
* @param {Object} params
|
|
129
|
+
* @returns {Object} Phoenix Channel
|
|
130
|
+
*/
|
|
131
|
+
}, {
|
|
132
|
+
key: "joinGroupChannel",
|
|
133
|
+
value: function joinGroupChannel(groupId) {
|
|
134
|
+
var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
135
|
+
return this._join("group:".concat(groupId), params);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Join the global groups feed.
|
|
140
|
+
* Topic: `"groups"`
|
|
141
|
+
* @param {Object} params
|
|
142
|
+
* @returns {Object} Phoenix Channel
|
|
143
|
+
*/
|
|
144
|
+
}, {
|
|
145
|
+
key: "joinGroupsChannel",
|
|
146
|
+
value: function joinGroupsChannel() {
|
|
147
|
+
var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
148
|
+
return this._join('groups', params);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Join a party channel for party events.
|
|
153
|
+
* Topic: `"party:<partyId>"`
|
|
154
|
+
* @param {string|number} partyId
|
|
155
|
+
* @param {Object} params
|
|
156
|
+
* @returns {Object} Phoenix Channel
|
|
157
|
+
*/
|
|
158
|
+
}, {
|
|
159
|
+
key: "joinPartyChannel",
|
|
160
|
+
value: function joinPartyChannel(partyId) {
|
|
161
|
+
var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
162
|
+
return this._join("party:".concat(partyId), params);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Join an arbitrary channel topic.
|
|
167
|
+
* @param {string} topic - Full Phoenix channel topic string
|
|
168
|
+
* @param {Object} params - Join params merged with the auth token
|
|
169
|
+
* @returns {Object} Phoenix Channel
|
|
170
|
+
*/
|
|
171
|
+
}, {
|
|
172
|
+
key: "joinChannel",
|
|
173
|
+
value: function joinChannel(topic) {
|
|
174
|
+
var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
175
|
+
return this._join(topic, params);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Leave and remove a channel by topic.
|
|
180
|
+
* @param {string} topic
|
|
181
|
+
*/
|
|
182
|
+
}, {
|
|
183
|
+
key: "leaveChannel",
|
|
184
|
+
value: function leaveChannel(topic) {
|
|
185
|
+
var ch = this._channels.get(topic);
|
|
186
|
+
if (ch) {
|
|
187
|
+
ch.leave();
|
|
188
|
+
this._channels["delete"](topic);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Retrieve an already-joined channel by topic.
|
|
194
|
+
* @param {string} topic
|
|
195
|
+
* @returns {Object|undefined} Phoenix Channel or undefined if not joined
|
|
196
|
+
*/
|
|
197
|
+
}, {
|
|
198
|
+
key: "channel",
|
|
199
|
+
value: function channel(topic) {
|
|
200
|
+
return this._channels.get(topic);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Access the underlying Phoenix.Socket instance.
|
|
205
|
+
* @returns {Object}
|
|
206
|
+
*/
|
|
207
|
+
}, {
|
|
208
|
+
key: "socket",
|
|
209
|
+
get: function get() {
|
|
210
|
+
return this._socket;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Disconnect the socket and leave all channels.
|
|
215
|
+
*/
|
|
216
|
+
}, {
|
|
217
|
+
key: "disconnect",
|
|
218
|
+
value: function disconnect() {
|
|
219
|
+
this._channels.forEach(function (ch) {
|
|
220
|
+
try {
|
|
221
|
+
ch.leave();
|
|
222
|
+
} catch (_) {}
|
|
223
|
+
});
|
|
224
|
+
this._channels.clear();
|
|
225
|
+
this._socket.disconnect();
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// ── Private ────────────────────────────────────────────────────────────────
|
|
229
|
+
}, {
|
|
230
|
+
key: "_join",
|
|
231
|
+
value: function _join(topic) {
|
|
232
|
+
var extraParams = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
233
|
+
if (this._channels.has(topic)) {
|
|
234
|
+
return this._channels.get(topic);
|
|
235
|
+
}
|
|
236
|
+
var ch = this._socket.channel(topic, _objectSpread({
|
|
237
|
+
token: this._token
|
|
238
|
+
}, extraParams));
|
|
239
|
+
ch.join().receive('error', function (err) {
|
|
240
|
+
return console.error("GameRealtime: failed to join channel \"".concat(topic, "\""), err);
|
|
241
|
+
});
|
|
242
|
+
this._channels.set(topic, ch);
|
|
243
|
+
return ch;
|
|
244
|
+
}
|
|
245
|
+
}]);
|
|
246
|
+
}();
|
|
247
|
+
var _default = exports["default"] = GameRealtime;
|
package/dist/webrtc.js
ADDED
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports["default"] = exports.GameWebRTC = void 0;
|
|
7
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
8
|
+
function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
|
|
9
|
+
function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
|
|
10
|
+
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
|
|
11
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
12
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
13
|
+
function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
|
|
14
|
+
function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
|
|
15
|
+
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
|
|
16
|
+
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
|
|
17
|
+
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
|
|
18
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
19
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
20
|
+
/**
|
|
21
|
+
* GameWebRTC — Browser WebRTC DataChannel client for game_server.
|
|
22
|
+
*
|
|
23
|
+
* Uses an existing Phoenix channel (e.g. from GameRealtime.joinUserChannel)
|
|
24
|
+
* for SDP/ICE signaling. Once connected, named DataChannels carry game data
|
|
25
|
+
* alongside the WebSocket at lower latency.
|
|
26
|
+
*
|
|
27
|
+
* Requires a browser with native WebRTC support (RTCPeerConnection).
|
|
28
|
+
* Does NOT work in Node.js without a WebRTC polyfill.
|
|
29
|
+
*
|
|
30
|
+
* Usage:
|
|
31
|
+
*
|
|
32
|
+
* import { GameRealtime, GameWebRTC } from '@ughuuu/game_server'
|
|
33
|
+
*
|
|
34
|
+
* const realtime = new GameRealtime('https://your-server.com', token)
|
|
35
|
+
* const userChannel = realtime.joinUserChannel(userId)
|
|
36
|
+
*
|
|
37
|
+
* const webrtc = new GameWebRTC(userChannel, {
|
|
38
|
+
* dataChannels: [
|
|
39
|
+
* { label: 'events', ordered: true },
|
|
40
|
+
* { label: 'state', ordered: false, maxRetransmits: 0 },
|
|
41
|
+
* ],
|
|
42
|
+
* onData: (label, data) => console.log('data', label, data),
|
|
43
|
+
* onChannelOpen: (label) => console.log('channel open', label),
|
|
44
|
+
* onChannelClose: (label) => console.log('channel close', label),
|
|
45
|
+
* onStateChange: (state) => console.log('state', state),
|
|
46
|
+
* })
|
|
47
|
+
*
|
|
48
|
+
* await webrtc.connect()
|
|
49
|
+
* webrtc.send('events', JSON.stringify({ type: 'player_move', x: 10, y: 20 }))
|
|
50
|
+
* webrtc.close()
|
|
51
|
+
*/
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Default DataChannel definitions.
|
|
55
|
+
* - "events": reliable, ordered — important game events
|
|
56
|
+
* - "state": unreliable, unordered — high-frequency position/state sync
|
|
57
|
+
*/
|
|
58
|
+
var DEFAULT_DATA_CHANNELS = [{
|
|
59
|
+
label: 'events',
|
|
60
|
+
ordered: true
|
|
61
|
+
}, {
|
|
62
|
+
label: 'state',
|
|
63
|
+
ordered: false,
|
|
64
|
+
maxRetransmits: 0
|
|
65
|
+
}];
|
|
66
|
+
var DEFAULT_ICE_SERVERS = [{
|
|
67
|
+
urls: 'stun:stun.l.google.com:19302'
|
|
68
|
+
}];
|
|
69
|
+
var GameWebRTC = exports.GameWebRTC = /*#__PURE__*/function () {
|
|
70
|
+
/**
|
|
71
|
+
* @param {Object} channel — A joined Phoenix channel (e.g. from GameRealtime.joinUserChannel)
|
|
72
|
+
* @param {Object} opts
|
|
73
|
+
* @param {Array} opts.dataChannels — Array of {label, ordered, maxRetransmits?} definitions
|
|
74
|
+
* @param {Array} opts.iceServers — RTCIceServer configs (default: Google STUN)
|
|
75
|
+
* @param {Function} opts.onData — (label: string, data: ArrayBuffer|string) => void
|
|
76
|
+
* @param {Function} opts.onChannelOpen — (label: string) => void
|
|
77
|
+
* @param {Function} opts.onChannelClose — (label: string) => void
|
|
78
|
+
* @param {Function} opts.onStateChange — (state: string) => void
|
|
79
|
+
* @param {Function} opts.onError — (error: Error) => void
|
|
80
|
+
*/
|
|
81
|
+
function GameWebRTC(channel) {
|
|
82
|
+
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
83
|
+
_classCallCheck(this, GameWebRTC);
|
|
84
|
+
this.channel = channel;
|
|
85
|
+
this.opts = opts;
|
|
86
|
+
this.iceServers = opts.iceServers || DEFAULT_ICE_SERVERS;
|
|
87
|
+
this.dataChannelDefs = opts.dataChannels || DEFAULT_DATA_CHANNELS;
|
|
88
|
+
|
|
89
|
+
/** @type {RTCPeerConnection|null} */
|
|
90
|
+
this.pc = null;
|
|
91
|
+
/** @type {Map<string, RTCDataChannel>} label → RTCDataChannel */
|
|
92
|
+
this.channels = new Map();
|
|
93
|
+
/** @type {string} */
|
|
94
|
+
this.connectionState = 'new';
|
|
95
|
+
this._resolveConnect = null;
|
|
96
|
+
this._rejectConnect = null;
|
|
97
|
+
this._setupChannelListeners();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// ── Public API ─────────────────────────────────────────────────────────────
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Initiate the WebRTC connection.
|
|
104
|
+
* Creates an RTCPeerConnection, opens DataChannels, sends an SDP offer
|
|
105
|
+
* over the Phoenix channel, and exchanges ICE candidates.
|
|
106
|
+
*
|
|
107
|
+
* @returns {Promise<void>} Resolves when at least one DataChannel is open.
|
|
108
|
+
*/
|
|
109
|
+
return _createClass(GameWebRTC, [{
|
|
110
|
+
key: "connect",
|
|
111
|
+
value: function () {
|
|
112
|
+
var _connect = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
|
|
113
|
+
var _this = this;
|
|
114
|
+
var _iterator, _step, def, dcOpts, dc, offer;
|
|
115
|
+
return _regenerator().w(function (_context) {
|
|
116
|
+
while (1) switch (_context.n) {
|
|
117
|
+
case 0:
|
|
118
|
+
this.pc = new RTCPeerConnection({
|
|
119
|
+
iceServers: this.iceServers
|
|
120
|
+
});
|
|
121
|
+
this.pc.onicecandidate = function (event) {
|
|
122
|
+
return _this._onIceCandidate(event);
|
|
123
|
+
};
|
|
124
|
+
this.pc.onconnectionstatechange = function () {
|
|
125
|
+
return _this._onConnectionStateChange();
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// Create DataChannels on the client side (client-initiated)
|
|
129
|
+
_iterator = _createForOfIteratorHelper(this.dataChannelDefs);
|
|
130
|
+
try {
|
|
131
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
132
|
+
def = _step.value;
|
|
133
|
+
dcOpts = {
|
|
134
|
+
ordered: def.ordered !== false
|
|
135
|
+
};
|
|
136
|
+
if (def.maxRetransmits !== undefined) dcOpts.maxRetransmits = def.maxRetransmits;
|
|
137
|
+
if (def.maxPacketLifeTime !== undefined) dcOpts.maxPacketLifeTime = def.maxPacketLifeTime;
|
|
138
|
+
dc = this.pc.createDataChannel(def.label, dcOpts);
|
|
139
|
+
this._wireDataChannel(dc);
|
|
140
|
+
this.channels.set(def.label, dc);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Create and send SDP offer
|
|
144
|
+
} catch (err) {
|
|
145
|
+
_iterator.e(err);
|
|
146
|
+
} finally {
|
|
147
|
+
_iterator.f();
|
|
148
|
+
}
|
|
149
|
+
_context.n = 1;
|
|
150
|
+
return this.pc.createOffer();
|
|
151
|
+
case 1:
|
|
152
|
+
offer = _context.v;
|
|
153
|
+
_context.n = 2;
|
|
154
|
+
return this.pc.setLocalDescription(offer);
|
|
155
|
+
case 2:
|
|
156
|
+
return _context.a(2, new Promise(function (resolve, reject) {
|
|
157
|
+
_this.channel.push('webrtc:offer', {
|
|
158
|
+
sdp: offer.sdp,
|
|
159
|
+
type: offer.type
|
|
160
|
+
}).receive('ok', function () {
|
|
161
|
+
// Offer accepted — wait for webrtc:answer from server
|
|
162
|
+
_this._resolveConnect = resolve;
|
|
163
|
+
_this._rejectConnect = reject;
|
|
164
|
+
}).receive('error', function (resp) {
|
|
165
|
+
reject(new Error(resp.error || 'webrtc:offer rejected'));
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// Timeout after 15 seconds
|
|
169
|
+
setTimeout(function () {
|
|
170
|
+
if (_this._resolveConnect) {
|
|
171
|
+
_this._resolveConnect = null;
|
|
172
|
+
reject(new Error('WebRTC connection timed out'));
|
|
173
|
+
}
|
|
174
|
+
}, 15000);
|
|
175
|
+
}));
|
|
176
|
+
}
|
|
177
|
+
}, _callee, this);
|
|
178
|
+
}));
|
|
179
|
+
function connect() {
|
|
180
|
+
return _connect.apply(this, arguments);
|
|
181
|
+
}
|
|
182
|
+
return connect;
|
|
183
|
+
}()
|
|
184
|
+
/**
|
|
185
|
+
* Send data over a named DataChannel.
|
|
186
|
+
* @param {string} label — channel label (e.g. "events" or "state")
|
|
187
|
+
* @param {string|ArrayBuffer|Blob} data
|
|
188
|
+
* @returns {boolean} true if sent, false if channel is not open
|
|
189
|
+
*/
|
|
190
|
+
}, {
|
|
191
|
+
key: "send",
|
|
192
|
+
value: function send(label, data) {
|
|
193
|
+
var dc = this.channels.get(label);
|
|
194
|
+
if (!dc || dc.readyState !== 'open') return false;
|
|
195
|
+
dc.send(data);
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Check if a specific DataChannel is open.
|
|
201
|
+
* @param {string} label
|
|
202
|
+
* @returns {boolean}
|
|
203
|
+
*/
|
|
204
|
+
}, {
|
|
205
|
+
key: "isChannelOpen",
|
|
206
|
+
value: function isChannelOpen(label) {
|
|
207
|
+
var dc = this.channels.get(label);
|
|
208
|
+
return dc ? dc.readyState === 'open' : false;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Check if the WebRTC connection is active.
|
|
213
|
+
* @returns {boolean}
|
|
214
|
+
*/
|
|
215
|
+
}, {
|
|
216
|
+
key: "isConnected",
|
|
217
|
+
value: function isConnected() {
|
|
218
|
+
return this.pc != null && this.connectionState === 'connected';
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Close the WebRTC connection and all DataChannels.
|
|
223
|
+
* Notifies the server via the Phoenix channel.
|
|
224
|
+
*/
|
|
225
|
+
}, {
|
|
226
|
+
key: "close",
|
|
227
|
+
value: function close() {
|
|
228
|
+
this._removeChannelListeners();
|
|
229
|
+
|
|
230
|
+
// Close all DataChannels
|
|
231
|
+
var _iterator2 = _createForOfIteratorHelper(this.channels.values()),
|
|
232
|
+
_step2;
|
|
233
|
+
try {
|
|
234
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
235
|
+
var dc = _step2.value;
|
|
236
|
+
try {
|
|
237
|
+
dc.close();
|
|
238
|
+
} catch (_) {}
|
|
239
|
+
}
|
|
240
|
+
} catch (err) {
|
|
241
|
+
_iterator2.e(err);
|
|
242
|
+
} finally {
|
|
243
|
+
_iterator2.f();
|
|
244
|
+
}
|
|
245
|
+
this.channels.clear();
|
|
246
|
+
|
|
247
|
+
// Close PeerConnection
|
|
248
|
+
if (this.pc) {
|
|
249
|
+
try {
|
|
250
|
+
this.pc.close();
|
|
251
|
+
} catch (_) {}
|
|
252
|
+
this.pc = null;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Notify server
|
|
256
|
+
this.channel.push('webrtc:close', {});
|
|
257
|
+
this.connectionState = 'closed';
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// ── Private: signaling channel listeners ──────────────────────────────────
|
|
261
|
+
}, {
|
|
262
|
+
key: "_setupChannelListeners",
|
|
263
|
+
value: function _setupChannelListeners() {
|
|
264
|
+
var _this2 = this;
|
|
265
|
+
// Server sends SDP answer
|
|
266
|
+
this._answerRef = this.channel.on('webrtc:answer', function (payload) {
|
|
267
|
+
if (_this2.pc) {
|
|
268
|
+
_this2.pc.setRemoteDescription(new RTCSessionDescription({
|
|
269
|
+
sdp: payload.sdp,
|
|
270
|
+
type: payload.type
|
|
271
|
+
}));
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
// Server sends ICE candidate
|
|
276
|
+
this._iceRef = this.channel.on('webrtc:ice', function (payload) {
|
|
277
|
+
if (_this2.pc && payload.candidate) {
|
|
278
|
+
_this2.pc.addIceCandidate(new RTCIceCandidate(payload))["catch"](function (err) {
|
|
279
|
+
return _this2._emitError(err);
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
// Server notifies about connection state changes
|
|
285
|
+
this._stateRef = this.channel.on('webrtc:state', function (payload) {
|
|
286
|
+
var cb = _this2.opts.onStateChange;
|
|
287
|
+
if (cb) cb(payload.state);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
// Server relays DataChannel data back via WebSocket (fallback)
|
|
291
|
+
this._dataRef = this.channel.on('webrtc:data', function (payload) {
|
|
292
|
+
var cb = _this2.opts.onData;
|
|
293
|
+
if (cb) cb(payload.channel, payload.data);
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
// Server confirms channel open
|
|
297
|
+
this._openRef = this.channel.on('webrtc:channel_open', function (payload) {
|
|
298
|
+
var cb = _this2.opts.onChannelOpen;
|
|
299
|
+
if (cb) cb(payload.channel);
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
}, {
|
|
303
|
+
key: "_removeChannelListeners",
|
|
304
|
+
value: function _removeChannelListeners() {
|
|
305
|
+
if (this._answerRef) this.channel.off('webrtc:answer', this._answerRef);
|
|
306
|
+
if (this._iceRef) this.channel.off('webrtc:ice', this._iceRef);
|
|
307
|
+
if (this._stateRef) this.channel.off('webrtc:state', this._stateRef);
|
|
308
|
+
if (this._dataRef) this.channel.off('webrtc:data', this._dataRef);
|
|
309
|
+
if (this._openRef) this.channel.off('webrtc:channel_open', this._openRef);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// ── Private: RTCPeerConnection event handlers ─────────────────────────────
|
|
313
|
+
}, {
|
|
314
|
+
key: "_onIceCandidate",
|
|
315
|
+
value: function _onIceCandidate(event) {
|
|
316
|
+
if (event.candidate) {
|
|
317
|
+
this.channel.push('webrtc:ice', event.candidate.toJSON());
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}, {
|
|
321
|
+
key: "_onConnectionStateChange",
|
|
322
|
+
value: function _onConnectionStateChange() {
|
|
323
|
+
var state = this.pc.connectionState;
|
|
324
|
+
this.connectionState = state;
|
|
325
|
+
var cb = this.opts.onStateChange;
|
|
326
|
+
if (cb) cb(state);
|
|
327
|
+
if (state === 'connected' && this._resolveConnect) {
|
|
328
|
+
this._resolveConnect();
|
|
329
|
+
this._resolveConnect = null;
|
|
330
|
+
this._rejectConnect = null;
|
|
331
|
+
}
|
|
332
|
+
if (state === 'failed' && this._rejectConnect) {
|
|
333
|
+
this._rejectConnect(new Error('WebRTC connection failed'));
|
|
334
|
+
this._resolveConnect = null;
|
|
335
|
+
this._rejectConnect = null;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// ── Private: DataChannel wiring ───────────────────────────────────────────
|
|
340
|
+
}, {
|
|
341
|
+
key: "_wireDataChannel",
|
|
342
|
+
value: function _wireDataChannel(dc) {
|
|
343
|
+
var _this3 = this;
|
|
344
|
+
dc.onopen = function () {
|
|
345
|
+
var cb = _this3.opts.onChannelOpen;
|
|
346
|
+
if (cb) cb(dc.label);
|
|
347
|
+
|
|
348
|
+
// Resolve connect() promise when the FIRST channel opens
|
|
349
|
+
if (_this3._resolveConnect) {
|
|
350
|
+
_this3._resolveConnect();
|
|
351
|
+
_this3._resolveConnect = null;
|
|
352
|
+
_this3._rejectConnect = null;
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
dc.onclose = function () {
|
|
356
|
+
var cb = _this3.opts.onChannelClose;
|
|
357
|
+
if (cb) cb(dc.label);
|
|
358
|
+
};
|
|
359
|
+
dc.onmessage = function (event) {
|
|
360
|
+
var cb = _this3.opts.onData;
|
|
361
|
+
if (cb) cb(dc.label, event.data);
|
|
362
|
+
};
|
|
363
|
+
dc.onerror = function (event) {
|
|
364
|
+
_this3._emitError(event.error || event);
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
}, {
|
|
368
|
+
key: "_emitError",
|
|
369
|
+
value: function _emitError(error) {
|
|
370
|
+
var cb = this.opts.onError;
|
|
371
|
+
if (cb) cb(error);
|
|
372
|
+
}
|
|
373
|
+
}]);
|
|
374
|
+
}();
|
|
375
|
+
var _default = exports["default"] = GameWebRTC;
|