XverseAvatarManager.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. const log = new Logger("xverse-avatar-manager")
  2. class XverseAvatarManager extends EventEmitter {
  3. constructor(e) {
  4. super();
  5. E(this, "xAvatarManager");
  6. E(this, "_room");
  7. E(this, "avatars", new Map);
  8. E(this, "syncAvatarsLength", 0);
  9. E(this, "broadcast");
  10. this._room = e,
  11. this._usersStatistics(),
  12. this.broadcast = this.setupBroadcast(),
  13. e.on("skinChanged", ()=>{
  14. this.avatars.forEach(t=>{
  15. t.disconnected && this.removeAvatar(t.userId, !0)
  16. }
  17. )
  18. }
  19. )
  20. }
  21. setupBroadcast() {
  22. return new Broadcast(this._room,async e=>{
  23. const {broadcastType: t, info: r} = e;
  24. if (t !== CoreBroadcastType.PlayAnimation)
  25. return;
  26. const {userId: n, animation: o, extra: a, loop: s=!1} = r
  27. , l = this.avatars.get(n);
  28. l && !l.isSelf && (l.emit("animationStart", {
  29. animationName: o,
  30. extra: decodeURIComponent(a)
  31. }),
  32. await (l == null ? void 0 : l._playAnimation(o, s)),
  33. l.emit("animationEnd", {
  34. animationName: o,
  35. extra: decodeURIComponent(a)
  36. }))
  37. }
  38. )
  39. }
  40. hideAll(e=!0) {
  41. this.xAvatarManager.hideAll(e)
  42. }
  43. showAll(e=!0) {
  44. this.xAvatarManager.showAll(e)
  45. }
  46. async init() {
  47. this.xAvatarManager = this._room.sceneManager.avatarComponent;
  48. try {
  49. const e = await this._room.modelManager.getApplicationConfig()
  50. , {avatars: t} = e;
  51. if (t) {
  52. await avatarLoader.parse(this._room.sceneManager, t);
  53. return
  54. }
  55. return Promise.reject("cannot find avatar config list")
  56. } catch (e) {
  57. return log.error(e),
  58. Promise.reject("avatar mananger init error!")
  59. }
  60. }
  61. async handleAvatar(e) {
  62. var r;
  63. if (this._room.viewMode === "simple" || !this._room.joined || !e.newUserStates)
  64. return;
  65. let t = e.newUserStates;
  66. if (((r = this._room._userAvatar) == null ? void 0 : r.isMoving) && this._room._userAvatar.motionType === MotionType.Run) {
  67. const n = t.filter(a=>a.userId === this._room.userId)
  68. , o = t.filter(a=>a.userId !== this._room.userId).slice(0, 2);
  69. t = n.concat(o)
  70. }
  71. if (e.getStateType === GetStateTypes.Event) {
  72. this.syncAvatarsLength = (t || []).length;
  73. const n = this._room.avatars.filter(s=>s.group == AvatarGroup.User);
  74. n.filter(s=>!(t != null && t.find(l=>l.userId == s.userId))).forEach(s=>{
  75. this.removeAvatar(s.userId)
  76. }
  77. );
  78. const a = t.filter(s=>!n.find(l=>l.userId == s.userId));
  79. this._handleAvatar(a)
  80. }
  81. this._handleAvatar(t)
  82. }
  83. async _handleAvatar(e) {
  84. e == null || e.forEach(t=>{
  85. var n, o, a, s, l, u, c, h, f;
  86. const r = this._room.userId === t.userId;
  87. if (((n = t.event) == null ? void 0 : n.type) === SyncEventType.ET_RemoveVisitor) {
  88. const d = (a = (o = t.event) == null ? void 0 : o.removeVisitorEvent) == null ? void 0 : a.removeVisitorEvent
  89. , _ = JSON.parse(safeDecodeURIComponent(((l = (s = t.event) == null ? void 0 : s.removeVisitorEvent) == null ? void 0 : l.extraInfo) || ""))
  90. , {code: g, msg: m} = _;
  91. d === RemoveVisitorType.RVT_ChangeToObserver ? this._room.audienceViewModeHook() : d === RemoveVisitorType.RVT_MoveOutOfTheRoom && this._room.leave(),
  92. this._room.emit("visitorStatusChanged", {
  93. code: g,
  94. msg: m
  95. })
  96. }
  97. if (t.event && [SyncEventType.Appear, SyncEventType.Reset].includes(t.event.type) || !t.event) {
  98. let d = this.avatars.get(t.userId);
  99. if (t.playerState.avatarId && (d == null ? void 0 : d.avatarId) !== t.playerState.avatarId && (d = void 0,
  100. this.removeAvatar(t.userId)),
  101. d) {
  102. if (d.disconnected && d.setConnectionStatus(!1),
  103. (u = t.event) != null && u.id && this._room.actionsHandler.confirmEvent(t.event.id),
  104. t.playerState.nickName && (d == null || d._setNickname(t.playerState.nickName)),
  105. t.playerState.avatarComponents && !d.isSelf && d.xAvatar) {
  106. const _ = safeParseComponents(t.playerState.avatarComponents);
  107. d._changeComponents({
  108. avatarComponents: _,
  109. mode: ChangeComponentsMode.Preview
  110. })
  111. }
  112. } else {
  113. const {position: _, angle: g} = t.playerState.player
  114. , m = t.playerState.avatarId
  115. , v = t.playerState.prioritySync
  116. , y = safelyJsonParse(t.playerState.extra);
  117. if (!m)
  118. return;
  119. const b = safeParseComponents(t.playerState.avatarComponents)
  120. , T = safeDecodeURIComponent(t.playerState.nickName)
  121. , C = this.calculatePriority(t.userId, y);
  122. this.addAvatar({
  123. userId: t.userId,
  124. isHost: t.playerState.isHost,
  125. nickname: T,
  126. avatarPosition: _,
  127. avatarRotation: g,
  128. avatarScale: t.playerState.avatarSize,
  129. avatarId: m,
  130. avatarComponents: t.playerState.person === Person.First ? [] : b,
  131. priority: C,
  132. group: AvatarGroup.User,
  133. prioritySync: v,
  134. extraInfo: y
  135. }).then(()=>{
  136. var A;
  137. (A = t.event) != null && A.id && this._room.actionsHandler.confirmEvent(t.event.id),
  138. this.updateAvatarPositionAndRotation(t),
  139. r && (this.xAvatarManager.setMainAvatar(t.userId),
  140. this._room.emit("userAvatarLoaded"),
  141. log.info("userAvatarLoaded"))
  142. }
  143. ).catch(A=>{
  144. r && (this.xAvatarManager.setMainAvatar(t.userId),
  145. this._room.emit("userAvatarFailed", {
  146. error: A
  147. }),
  148. log.error("userAvatarFailed", A))
  149. }
  150. )
  151. }
  152. }
  153. if (t.event && SyncEventType.Disappear === t.event.type && ((c = t == null ? void 0 : t.event) != null && c.id && this._room.actionsHandler.confirmEvent(t.event.id),
  154. this.removeAvatar(t.userId)),
  155. t.event && [SyncEventType.Move, SyncEventType.ChangeRenderInfo].includes(t.event.type) || !t.event) {
  156. (h = t == null ? void 0 : t.event) != null && h.id && this._room.actionsHandler.confirmEvent(t.event.id);
  157. const d = this.avatars.get(t.userId);
  158. d && d.withModel && !d.isLoading && this.updateAvatarPositionAndRotation(t)
  159. }
  160. if (!r && ((f = t.event) == null ? void 0 : f.type) === SyncEventType.Rotate) {
  161. const d = this.avatars.get(t.userId);
  162. d.statusSyncQueue.append({
  163. type: QueueType.Rotate,
  164. action: ()=>d.statusSync(t)
  165. })
  166. }
  167. }
  168. )
  169. }
  170. calculatePriority(e, t) {
  171. var n;
  172. return e === this._room.userId ? EAvatarRelationRank.Self : (n = this._room.options.firends) != null && n.includes(e) ? EAvatarRelationRank.Friend : EAvatarRelationRank.Stranger
  173. }
  174. updateAvatarPositionAndRotation(e) {
  175. var t, r;
  176. if ((t = e == null ? void 0 : e.playerState) != null && t.player) {
  177. let {position: n, angle: o} = e.playerState.player;
  178. const a = this.avatars.get(e.userId);
  179. if (!a)
  180. return;
  181. if (n = positionPrecisionProtect(n),
  182. o = rotationPrecisionProtect(o),
  183. a.isSelf && !this._room.networkController.rtcp.workers.inPanoMode && (a.setPosition(n),
  184. a.setRotation(o)),
  185. e.event && (((r = e.event) == null ? void 0 : r.points.length) || 0) > 1 && !a.isSelf && a.statusSyncQueue.append({
  186. type: QueueType.Move,
  187. action: ()=>a.statusSync(e)
  188. }),
  189. e.renderInfo && a.isSelf) {
  190. const {isMoving: s, isRotating: l} = e.renderInfo;
  191. this._updateAvatarMovingStatus({
  192. id: e.userId,
  193. isMoving: !!s,
  194. isRotating: !!l
  195. })
  196. }
  197. }
  198. }
  199. async addAvatar(e) {
  200. const {userId: t, isHost: r, avatarPosition: n, avatarId: o, avatarRotation: a, nickname: s, avatarComponents: l=[], priority: u, group: c=AvatarGroup.Npc, avatarScale: h=DEFAULT_AVATAR_SCALE, extraInfo: f, prioritySync: d} = e
  201. , _ = t === this._room.userId;
  202. let g = this.avatars.get(t);
  203. if (g)
  204. return Promise.resolve(g);
  205. if (g = new xe.subAvatar({
  206. userId: t,
  207. isHost: r,
  208. isSelf: _,
  209. room: this._room,
  210. avatarComponents: l,
  211. avatarId: o,
  212. nickname: s,
  213. group: c
  214. }),
  215. this.avatars.set(t, g),
  216. !g.withModel)
  217. return g.isLoading = !1,
  218. g.avatarLoadedHook(),
  219. this._room.emit("avatarChanged", {
  220. avatars: this._room.avatars
  221. }),
  222. g;
  223. const v = (await this._room.modelManager.getAvatarModelList()).find(b=>b.id === o)
  224. , y = Date.now();
  225. if (!v)
  226. return this._room.emit("avatarChanged", {
  227. avatars: this._room.avatars
  228. }),
  229. this.avatars.delete(t),
  230. Promise.reject(`no such avatar model with id: ${o}`);
  231. try {
  232. let b = await avatarComponentsModify(v, l);
  233. b = b.filter(A=>A.type != "pendant");
  234. const T = await avatarComponentsParser(v, b)
  235. , C = await this.xAvatarManager.loadAvatar({
  236. id: t,
  237. avatarType: o,
  238. priority: u,
  239. avatarManager: this.xAvatarManager,
  240. assets: T,
  241. status: {
  242. avatarPosition: n,
  243. avatarRotation: a,
  244. avatarScale: h
  245. }
  246. })._timeout(8e3, new TimeoutError$1("loadAvatar timeout(8s)"));
  247. return C.setPickBoxScale(t === this._room.userId ? 0 : 1),
  248. g.xAvatar = C,
  249. g.setScale(h),
  250. g.extraInfo = f,
  251. g.priority = u,
  252. g.isLoading = !1,
  253. g.prioritySync = !!d,
  254. g._playAnimation("Idle", !0, !0),
  255. g.avatarLoadedHook(),
  256. this._room.emit("avatarChanged", {
  257. avatars: this._room.avatars
  258. }),
  259. s && g._setNickname(s),
  260. t === this._room.userId && (log.infoAndReportMeasurement({
  261. metric: "avatarLoadDuration",
  262. startTime: y,
  263. group: "costs"
  264. }),
  265. log.infoAndReportMeasurement({
  266. metric: "avatarLoadAt",
  267. startTime: this._room._startTime,
  268. group: "costs"
  269. })),
  270. g
  271. } catch (b) {
  272. return g.isLoading = !1,
  273. this._room.emit("avatarChanged", {
  274. avatars: this._room.avatars
  275. }),
  276. log.error(b),
  277. Promise.reject(b)
  278. }
  279. }
  280. removeAvatar(e, t=!1) {
  281. const r = this.avatars.get(e);
  282. if (!!r) {
  283. if (r.removeWhenDisconnected || t) {
  284. r.xAvatar && this.xAvatarManager.deleteAvatar(r.xAvatar),
  285. this.avatars.delete(e),
  286. this._room.emit("avatarChanged", {
  287. avatars: this._room.avatars
  288. });
  289. return
  290. }
  291. r.setConnectionStatus(!0)
  292. }
  293. }
  294. clearOtherUsers() {
  295. this.avatars.forEach(e=>{
  296. !e.isSelf && e.group === AvatarGroup.User && this.removeAvatar(e.userId)
  297. }
  298. )
  299. }
  300. async _updateAvatarMovingStatus(e) {
  301. const {id: t, isMoving: r, isRotating: n} = e
  302. , o = this.avatars.get(t);
  303. if (!!o) {
  304. if (o.isRotating !== n) {
  305. o.isRotating = n;
  306. let a = "Idle";
  307. n && (a = "Walking",
  308. o.motionType === MotionType.Run && (a = "Running")),
  309. o._playAnimation(a, !0, !0),
  310. log.infoAndReportMeasurement({
  311. startTime: Date.now(),
  312. value: 0,
  313. metric: n ? "userAvatarStartRotating" : "userAvatarStopRotating",
  314. extra: {
  315. motionType: o.motionType,
  316. moveToExtra: this._room.moveToExtra
  317. }
  318. })
  319. }
  320. if (o.isMoving !== r) {
  321. o.isMoving = r;
  322. let a = "Idle";
  323. r && (a = "Walking",
  324. o.motionType === MotionType.Run && (a = "Running")),
  325. r ? (o.avatarStartMovingHook(),
  326. o.emit("startMoving", {
  327. target: o,
  328. extra: this._room.moveToExtra
  329. })) : (o.avatarStopMovingHook(),
  330. o.emit("stopMoving", {
  331. target: o,
  332. extra: this._room.moveToExtra
  333. })),
  334. o._playAnimation(a, !0, !0),
  335. log.infoAndReportMeasurement({
  336. startTime: Date.now(),
  337. value: 0,
  338. metric: r ? "userAvatarStartMoving" : "userAvatarStopMoving",
  339. extra: {
  340. motionType: o.motionType,
  341. moveToExtra: this._room.moveToExtra
  342. }
  343. })
  344. }
  345. }
  346. }
  347. _usersStatistics() {
  348. this.on("userAvatarLoaded", ()=>{
  349. window.setInterval(()=>{
  350. const e = this._room.avatars.filter(r=>r.group === AvatarGroup.User).length || 0
  351. , t = this._room.avatars.filter(r=>r.group === AvatarGroup.User && r.isRender).length || 0;
  352. this._room.stats.assign({
  353. userNum: e,
  354. syncUserNum: this.syncAvatarsLength,
  355. renderedUserNum: t
  356. })
  357. }
  358. , 3e3)
  359. }
  360. )
  361. }
  362. }
  363. ;