rotate.service.ts 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. import { Injectable, Logger } from '@nestjs/common';
  2. import { CacheService } from 'src/cache/cache.service';
  3. // import { SceneService } from 'src/scene/scene.service';
  4. const seqExeAsyncFn = (asyncFn) => {
  5. let runPromise = null;
  6. return function seq(...args) {
  7. if (!runPromise) {
  8. //debugger;
  9. runPromise = asyncFn.apply(this, args);
  10. runPromise.then((data) => {
  11. //debugger;
  12. // console.log('seq result', data);
  13. });
  14. runPromise.then(() => (runPromise = null));
  15. return runPromise;
  16. } else {
  17. return runPromise.then(() => seq.apply(this, args));
  18. }
  19. };
  20. };
  21. @Injectable()
  22. export class RotateService {
  23. constructor(
  24. private cacheService: CacheService, // private sceneService: SceneService,
  25. ) {}
  26. private actionRequestPool = {};
  27. private logger: Logger = new Logger('rotateService');
  28. private Actions = {
  29. Clicking: 1,
  30. Rotation: 1014,
  31. Joystick: 15,
  32. };
  33. public users = {};
  34. private replies = {};
  35. init(app_id: string, userId: string) {
  36. const user = {
  37. appId: null,
  38. userId: null,
  39. breakPointId: null,
  40. roomId: null,
  41. player: {
  42. position: { x: -800.0, y: 100.0, z: 0.0 },
  43. angle: {
  44. pitch: 0,
  45. yaw: 0,
  46. roll: 0,
  47. },
  48. },
  49. camera: {
  50. position: { x: -1139.3031005859375, y: 99.99999237060548, z: 120.0 },
  51. angle: {
  52. pitch: 0,
  53. yaw: 0,
  54. roll: 0,
  55. },
  56. },
  57. rotateInfo: {
  58. frameIndex: 0,
  59. horizontal_move: 0,
  60. },
  61. moveInfo: {},
  62. // traceIds: [],
  63. // actionResponses:[]
  64. };
  65. user.appId = app_id;
  66. user.userId = userId;
  67. user.breakPointId = 93;
  68. this.users[userId] = user;
  69. const reply = {
  70. traceIds: [],
  71. vehicle: null,
  72. mediaSrc: null,
  73. newUserStates: [
  74. {
  75. userId: 'dcff36ae4fc1d',
  76. playerState: {
  77. roomTypeId: '',
  78. person: 0,
  79. avatarId: '',
  80. skinId: '',
  81. roomId: '',
  82. isHost: false,
  83. isFollowHost: false,
  84. skinDataVersion: '',
  85. avatarComponents: '',
  86. nickName: '',
  87. movingMode: 0,
  88. attitude: '',
  89. areaName: '',
  90. pathName: '',
  91. pathId: '',
  92. avatarSize: 1,
  93. extra: '',
  94. prioritySync: false,
  95. player: {
  96. position: { x: 100.0, y: 100.0, z: 0.0 },
  97. angle: {
  98. pitch: 0,
  99. yaw: 0,
  100. roll: 0,
  101. },
  102. },
  103. camera: {
  104. position: { x: -338.0, y: 100, z: 120.0 },
  105. angle: {
  106. pitch: 0,
  107. yaw: 0,
  108. roll: 0,
  109. },
  110. },
  111. cameraCenter: { x: 100.0, y: 100.0, z: 0.0 },
  112. },
  113. renderInfo: {
  114. renderType: 0,
  115. videoFrame: null,
  116. cameraStateType: 3,
  117. isMoving: 0,
  118. needIfr: 0,
  119. isVideo: 0,
  120. stillFrame: 0,
  121. isRotating: 0,
  122. isFollowing: 0,
  123. clientPanoTitlesBitmap: [],
  124. clientPanoTreceId: '',
  125. prefetchVideoId: '',
  126. noMedia: false,
  127. },
  128. event: null,
  129. relation: 1,
  130. },
  131. ],
  132. actionResponses: [
  133. // {
  134. // "actionType": 15,
  135. // "pointType": 100,
  136. // "extra": "",
  137. // "traceId": "d0864cd0-378d-4d49-b7b0-3e8e1b9494c3",
  138. // "packetId": "d44bd2f5-f877-4dd7-868b-803c64f99082",
  139. // "nps": [],
  140. // "peopleNum": 0,
  141. // "zoneId": "",
  142. // "echoMsg": "",
  143. // "reserveDetail": null,
  144. // "userWithAvatarList": [],
  145. // "newUserStates": [],
  146. // "code": 0,
  147. // "msg": ""
  148. // }
  149. ],
  150. getStateType: 0,
  151. code: 0,
  152. msg: 'OK',
  153. };
  154. reply['newUserStates'][0]['userId'] = userId;
  155. this.replies[userId] = reply;
  156. return reply;
  157. }
  158. // 顺序旋转请求
  159. seqExeRotate = seqExeAsyncFn(this.rotate);
  160. //旋转请求
  161. async rotate(actionRequest) {
  162. // return new Promise(async (resolve, reject) => {
  163. try {
  164. const userId = actionRequest['user_id'];
  165. if (this.actionRequestPool[userId]) {
  166. this.actionRequestPool[userId].push(actionRequest);
  167. } else {
  168. this.actionRequestPool[userId] = [];
  169. this.actionRequestPool[userId].push(actionRequest);
  170. }
  171. let reply = this.replies[userId];
  172. const actionRequests = this.actionRequestPool[userId];
  173. const user = this.users[userId];
  174. // debugger;
  175. let horizontal_move = user.rotateInfo.horizontal_move;
  176. //const traceIds = user.traceIds;
  177. let sub = 0;
  178. for (let i = 0; i < actionRequests.length; ++i) {
  179. if (actionRequests[i].action_type == this.Actions.Rotation) {
  180. horizontal_move += actionRequests[i].rotation_action.horizontal_move;
  181. reply.traceIds.push(actionRequests[i].trace_id);
  182. const actionResponse = this.createActionResponse(
  183. actionRequests[i].action_type,
  184. actionRequests[i].trace_id,
  185. );
  186. reply.actionResponses.push(actionResponse);
  187. ++sub;
  188. } else {
  189. break;
  190. }
  191. }
  192. actionRequests.splice(0, sub);
  193. const hAngle = horizontal_move * 90;
  194. if (Math.abs(hAngle) < 1) {
  195. user.rotateInfo.horizontal_move = horizontal_move;
  196. //user.traceIds = traceIds;
  197. this.replies[userId] = reply;
  198. return null;
  199. }
  200. reply = await this.rotateForAngle(userId, Math.floor(hAngle));
  201. // console.log('rotate-cameraAngle:, yaw: %s, ', user.camera.angle.yaw);
  202. return reply;
  203. // return resolve(reply);
  204. } catch (error) {
  205. throw error;
  206. // console.log('RotateService', error);
  207. // return reject(error);
  208. }
  209. // });
  210. }
  211. // test(){
  212. // while(true){
  213. // if(this.actionRequests.length>0){
  214. // let actionRequest = this.actionRequests[0];
  215. // //执行
  216. // //添加队列
  217. // }
  218. // }
  219. // }
  220. // receiveRotate(actionRequest){
  221. // this.actionRequests.push(actionRequest)
  222. // }
  223. rotateForAngle(userId, hAngle): Promise<any> {
  224. return new Promise(async (resolve, reject) => {
  225. try {
  226. const user = this.users[userId];
  227. // console.log(
  228. // '当前镜头角度, yaw: %s, hAngle: %s',
  229. // user.camera.angle.yaw,
  230. // hAngle,
  231. // );
  232. // console.time('当前镜头角度 %s', user.camera.angle.yaw, '旋转角度:', hAngle);
  233. user.camera.angle.yaw += Math.floor(hAngle);
  234. if (user.camera.angle.yaw < 0) {
  235. user.camera.angle.yaw = 360 + user.camera.angle.yaw;
  236. } else if (user.camera.angle.yaw > 359) {
  237. user.camera.angle.yaw -= 360;
  238. }
  239. const reply = JSON.parse(JSON.stringify(this.replies[userId]));
  240. reply['newUserStates'][0]['userId'] = userId;
  241. //从redis里取
  242. //let key = user.appId + "-"+user.breakPointId+"-"+user.rotateInfo.frameIndex;
  243. const key =
  244. 'rotateframe:app_id:' +
  245. user.appId +
  246. ':frame_index:' +
  247. user.camera.angle.yaw +
  248. ':break_point_id:' +
  249. user.breakPointId;
  250. // const value = null;
  251. const redisData = await this.cacheService.get(key);
  252. //if (redisData && redisData.length > 0) {
  253. const value = JSON.parse(redisData); //redisData ? JSON.parse(redisData) : null;
  254. // console.log('rotate-service', value);
  255. user.camera['position'] = JSON.parse(JSON.stringify(value.cameraPosition)); //value ? value.cameraPosition : '';
  256. user.camera['angle'] = JSON.parse(JSON.stringify(value.cameraAngle)); //value ? value.cameraAngle : '';
  257. reply['newUserStates'][0]['playerState'].player.position = JSON.parse(JSON.stringify(user.player.position));
  258. reply['newUserStates'][0]['playerState'].player.angle = JSON.parse(JSON.stringify(user.player.angle));
  259. //this.reply['newUserStates'][0]['playerState'] .player
  260. reply['newUserStates'][0]['playerState'].camera.position = JSON.parse(JSON.stringify(value.cameraPosition));
  261. reply['newUserStates'][0]['playerState'].camera.angle = JSON.parse(JSON.stringify(value.cameraAngle));
  262. reply['newUserStates'][0]['playerState'].cameraCenter = JSON.parse(JSON.stringify(user.player.position));
  263. // debugger
  264. reply.mediaSrc =
  265. '/' +
  266. user.appId +
  267. '/' +
  268. user.breakPointId +
  269. '/' +
  270. value.directory +
  271. '/' +
  272. value.fileName +
  273. '?m=' +
  274. new Date().getTime();
  275. reply.breakPointId = user.breakPointId;
  276. this.replies[userId].traceIds = [];
  277. this.replies[userId].actionResponses = [];
  278. user.rotateInfo.horizontal_move = 0;
  279. return resolve(reply);
  280. //}
  281. // else {
  282. // return null;
  283. // }
  284. } catch (error) {
  285. this.logger.error('rotateForAngle::function', error);
  286. return reject(error);
  287. }
  288. });
  289. }
  290. createActionResponse(actionType, traceId) {
  291. const actionResponse = {
  292. actionType: actionType,
  293. pointType: 100,
  294. extra: '',
  295. traceId: traceId,
  296. packetId: '',
  297. nps: [],
  298. peopleNum: 0,
  299. zoneId: '',
  300. echoMsg: '',
  301. reserveDetail: null,
  302. userWithAvatarList: [],
  303. newUserStates: [],
  304. code: 0,
  305. msg: '',
  306. };
  307. return actionResponse;
  308. }
  309. getNewUserStateRequest(actionRequest) {
  310. try {
  311. const userId = actionRequest['user_id'];
  312. const actionType = actionRequest['action_type'];
  313. const traceId = actionRequest['trace_id'];
  314. const reply = {
  315. actionType: actionType,
  316. pointType: 100,
  317. extra: '',
  318. traceId: traceId,
  319. packetId: '',
  320. nps: [],
  321. peopleNum: 0,
  322. zoneId: '',
  323. echoMsg: '',
  324. reserveDetail: null,
  325. userWithAvatarList: [],
  326. newUserStates: [],
  327. code: 0,
  328. msg: '',
  329. };
  330. const userIds = Object.keys(this.users);
  331. for (let i = 0; i < userIds.length; ++i) {
  332. const _user = this.users[userIds[i]];
  333. const newUserState = {
  334. userId: userIds[i],
  335. playerState: {
  336. roomTypeId: '',
  337. person: 0,
  338. avatarId: 'KGe_Boy',
  339. skinId: '10089',
  340. roomId: 'e629ef3e-022d-4e64-8654-703bb96410eb',
  341. isHost: false,
  342. isFollowHost: false,
  343. skinDataVersion: '1008900008',
  344. avatarComponents: '',
  345. nickName: userIds[i],
  346. movingMode: 0,
  347. attitude: 'walk',
  348. areaName: '',
  349. pathName: 'thirdwalk',
  350. pathId: 'thirdwalk',
  351. avatarSize: 1,
  352. extra: '{"removeWhenDisconnected":true}',
  353. prioritySync: false,
  354. player: {
  355. position: _user.player.position,
  356. angle: _user.player.angle,
  357. },
  358. camera: null,
  359. cameraCenter: null,
  360. },
  361. renderInfo: {
  362. renderType: 0,
  363. videoFrame: null,
  364. cameraStateType: 0,
  365. isMoving: 0,
  366. needIfr: 0,
  367. isVideo: 0,
  368. stillFrame: 0,
  369. isRotating: 0,
  370. isFollowing: 0,
  371. clientPanoTitlesBitmap: [],
  372. clientPanoTreceId: '',
  373. prefetchVideoId: '',
  374. noMedia: false,
  375. },
  376. event: {
  377. id: '',
  378. type: 0,
  379. points: [],
  380. rotateEvent: null,
  381. removeVisitorEvent: null,
  382. },
  383. relation: 0,
  384. };
  385. reply['newUserStates'].push(newUserState);
  386. }
  387. return reply;
  388. } catch (error) {
  389. this.logger.error('getNewUserStateRequest::function', error);
  390. }
  391. }
  392. async echo(userId: string, isFirst: boolean) {
  393. const user = this.users[userId];
  394. const reply = JSON.parse(JSON.stringify(this.replies[userId]));
  395. reply['newUserStates'][0]['userId'] = userId;
  396. reply['newUserStates'][0]['playerState'].player.position =
  397. user.player.position;
  398. reply['newUserStates'][0]['playerState'].player.angle = user.player.angle;
  399. reply['newUserStates'][0]['playerState'].camera.position =
  400. user.camera['position'];
  401. reply['newUserStates'][0]['playerState'].camera.angle =
  402. user.camera['angle'];
  403. reply['newUserStates'][0]['playerState'].cameraCenter =
  404. user.player.position;
  405. if (isFirst) {
  406. reply.mediaSrc =
  407. '/' +
  408. user.appId +
  409. '/' +
  410. user.breakPointId +
  411. '/' +
  412. user.breakPointId +
  413. '/' +
  414. `${user.breakPointId}.0000.h264` +
  415. '?m=' +
  416. new Date().getTime();
  417. reply.breakPointId = user.breakPointId;
  418. return reply;
  419. } else {
  420. const key =
  421. 'rotateframe:app_id:' +
  422. user.appId +
  423. ':frame_index:' +
  424. user.camera.angle.yaw +
  425. ':break_point_id:' +
  426. user.breakPointId;
  427. const redisData = await this.cacheService.get(key);
  428. if (redisData && redisData.length > 0) {
  429. const value = redisData ? JSON.parse(redisData) : null;
  430. reply.mediaSrc =
  431. '/' +
  432. user.appId +
  433. '/' +
  434. user.breakPointId +
  435. '/' +
  436. value.directory +
  437. '/' +
  438. value.fileName +
  439. '?m=' +
  440. new Date().getTime();
  441. reply.breakPointId = user.breakPointId;
  442. return reply;
  443. } else {
  444. this.logger.error('echo返回null', key);
  445. return {};
  446. }
  447. }
  448. }
  449. }