XverseAvatarManager.js 16 KB

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