Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

470 строки
10 KiB

  1. let roles = require('../config/roles');
  2. let events = require('../misc/events');
  3. const profanities = require('../misc/profanities');
  4. module.exports = {
  5. type: 'social',
  6. isPartyLeader: null,
  7. partyLeaderId: null,
  8. party: null,
  9. customChannels: null,
  10. blockedPlayers: [],
  11. messageHistory: [],
  12. maxChatLength: 255,
  13. init: function (blueprint) {
  14. this.obj.extendComponent('social', 'socialCommands', {});
  15. if (blueprint)
  16. this.blockedPlayers = blueprint.blockedPlayers || [];
  17. },
  18. simplify: function (self) {
  19. return {
  20. type: 'social',
  21. party: this.party,
  22. customChannels: self ? this.customChannels : null,
  23. blockedPlayers: self ? this.blockedPlayers : null,
  24. muted: this.muted
  25. };
  26. },
  27. save: function () {
  28. return {
  29. type: 'social',
  30. customChannels: this.customChannels,
  31. blockedPlayers: this.blockedPlayers,
  32. muted: this.muted || null
  33. };
  34. },
  35. sendMessage: function (msg, color, target) {
  36. (target || this.obj).socket.emit('event', {
  37. event: 'onGetMessages',
  38. data: {
  39. messages: [{
  40. class: color || 'q0',
  41. message: msg,
  42. type: 'chat'
  43. }]
  44. }
  45. });
  46. },
  47. sendPartyMessage: function (msg) {
  48. if (!this.party) {
  49. this.obj.socket.emit('events', {
  50. onGetMessages: [{
  51. messages: [{
  52. class: 'color-redA',
  53. message: 'you are not in a party',
  54. type: 'info'
  55. }]
  56. }]
  57. });
  58. return;
  59. }
  60. let charname = this.obj.auth.charname;
  61. let message = msg.data.message.substr(1);
  62. this.party.forEach(function (p) {
  63. let player = cons.players.find(c => c.id === p);
  64. player.socket.emit('events', {
  65. onGetMessages: [{
  66. messages: [{
  67. class: 'color-grayB',
  68. message: '(party: ' + charname + '): ' + message,
  69. type: 'chat',
  70. source: this.obj.name
  71. }]
  72. }]
  73. });
  74. }, this);
  75. },
  76. sendCustomChannelMessage: function (msg) {
  77. let pList = cons.players;
  78. let pLen = pList.length;
  79. let origMessage = msg.data.message.substr(1);
  80. let channel = origMessage.split(' ')[0];
  81. let message = origMessage.substr(channel.length);
  82. if ((!channel) || (!message)) {
  83. this.obj.socket.emit('events', {
  84. onGetMessages: [{
  85. messages: [{
  86. class: 'color-redA',
  87. message: 'syntax: $channel message',
  88. type: 'info'
  89. }]
  90. }]
  91. });
  92. return;
  93. } else if (!this.isInChannel(this.obj, channel)) {
  94. this.obj.socket.emit('events', {
  95. onGetMessages: [{
  96. messages: [{
  97. class: 'color-redA',
  98. message: 'you are not currently in channel: ' + channel,
  99. type: 'info'
  100. }]
  101. }]
  102. });
  103. return;
  104. } else if (pLen > 0) {
  105. for (let i = 0; i < pLen; i++) {
  106. if (this.isInChannel(pList[i], channel)) {
  107. pList[i].socket.emit('events', {
  108. onGetMessages: [{
  109. messages: [{
  110. class: 'color-grayB',
  111. message: '[' + channel + '] ' + this.obj.auth.charname + ': ' + message,
  112. type: channel.trim(),
  113. source: this.obj.name
  114. }]
  115. }]
  116. });
  117. }
  118. }
  119. }
  120. },
  121. chat: function (msg) {
  122. if (!msg.data.message)
  123. return;
  124. msg.data.message = msg.data.message
  125. .split('<')
  126. .join('&lt;')
  127. .split('>')
  128. .join('&gt;');
  129. if (!msg.data.message)
  130. return;
  131. if (msg.data.message.trim() === '')
  132. return;
  133. if (this.muted) {
  134. this.sendMessage('You have been muted from talking', 'color-redA');
  135. return;
  136. }
  137. let messageString = msg.data.message;
  138. if (messageString.length > this.maxChatLength)
  139. return;
  140. let history = this.messageHistory;
  141. let time = +new Date();
  142. history.spliceWhere(h => ((time - h.time) > 5000));
  143. if (history.length > 0) {
  144. if (history[history.length - 1].msg === messageString) {
  145. this.sendMessage('You have already sent that message', 'color-redA');
  146. return;
  147. } else if (history.length >= 3) {
  148. this.sendMessage('You are sending too many messages', 'color-redA');
  149. return;
  150. }
  151. }
  152. this.onBeforeChat(msg.data);
  153. if (msg.data.ignore)
  154. return;
  155. if (!msg.data.item && !profanities.isClean(messageString)) {
  156. this.sendMessage('Profanities detected in message. Blocked.', 'color-redA');
  157. return;
  158. }
  159. history.push({
  160. msg: messageString,
  161. time: time
  162. });
  163. let charname = this.obj.auth.charname;
  164. let msgStyle = roles.getRoleMessageStyle(this.obj) || ('color-grayB');
  165. let msgEvent = {
  166. source: charname,
  167. msg: messageString
  168. };
  169. events.emit('onBeforeSendMessage', msgEvent);
  170. messageString = msgEvent.msg;
  171. if (messageString[0] === '@') {
  172. let playerName = '';
  173. //Check if there's a space in the name
  174. if (messageString[1] === "'") {
  175. playerName = messageString.substring(2, messageString.indexOf("'", 2));
  176. messageString = messageString.replace("@'" + playerName + "' ", '');
  177. } else {
  178. playerName = messageString.substring(1, messageString.indexOf(' '));
  179. messageString = messageString.replace('@' + playerName + ' ', '');
  180. }
  181. if (playerName === this.obj.name)
  182. return;
  183. let target = cons.players.find(p => p.name === playerName);
  184. if (!target)
  185. return;
  186. this.obj.socket.emit('event', {
  187. event: 'onGetMessages',
  188. data: {
  189. messages: [{
  190. class: 'color-yellowB',
  191. message: '(you to ' + playerName + '): ' + messageString,
  192. type: 'chat',
  193. source: this.obj.name
  194. }]
  195. }
  196. });
  197. target.socket.emit('event', {
  198. event: 'onGetMessages',
  199. data: {
  200. messages: [{
  201. class: 'color-yellowB',
  202. message: '(' + this.obj.name + ' to you): ' + messageString,
  203. type: 'chat',
  204. source: this.obj.name
  205. }]
  206. }
  207. });
  208. } else if (messageString[0] === '$')
  209. this.sendCustomChannelMessage(msg);
  210. else if (messageString[0] === '%')
  211. this.sendPartyMessage(msg);
  212. else {
  213. let prefix = roles.getRoleMessagePrefix(this.obj) || '';
  214. cons.emit('event', {
  215. event: 'onGetMessages',
  216. data: {
  217. messages: [{
  218. class: msgStyle,
  219. message: prefix + charname + ': ' + msg.data.message,
  220. item: msg.data.item,
  221. type: 'chat',
  222. source: this.obj.name
  223. }]
  224. }
  225. });
  226. }
  227. },
  228. dc: function () {
  229. if (!this.party)
  230. return;
  231. this.leaveParty();
  232. },
  233. //This gets called on the target player
  234. getInvite: function (msg) {
  235. if (this.party)
  236. return;
  237. let obj = this.obj;
  238. let sourceId = msg.data.sourceId;
  239. if (sourceId === obj.id)
  240. return;
  241. let source = cons.players.find(c => c.id === sourceId);
  242. if (!source)
  243. return;
  244. source.social.sendMessage('invite sent', 'color-yellowB');
  245. this.sendMessage(source.name + ' has invited you to join a party', 'color-yellowB');
  246. this.obj.socket.emit('event', {
  247. event: 'onGetInvite',
  248. data: sourceId
  249. });
  250. },
  251. //This gets called on the player that initiated the invite
  252. acceptInvite: function (msg) {
  253. let sourceId = msg.data.sourceId;
  254. let source = cons.players.find(c => c.id === sourceId);
  255. if (!source)
  256. return;
  257. if (!this.party) {
  258. this.isPartyLeader = true;
  259. this.party = [this.obj.id];
  260. this.updateMainThread('party', this.party);
  261. }
  262. // Only add if not yet in party
  263. if (!this.party.find(id => (id === sourceId)))
  264. this.party.push(sourceId);
  265. this.updateMainThread('party', this.party);
  266. this.party.forEach(function (p) {
  267. let player = cons.players.find(c => c.id === p);
  268. player.social.party = this.party;
  269. player.social.updateMainThread('party', player.social.party);
  270. let returnMsg = source.name + ' has joined the party';
  271. if (p === sourceId)
  272. returnMsg = 'you have joined a party';
  273. player.social.sendMessage(returnMsg, 'color-yellowB');
  274. player
  275. .socket.emit('event', {
  276. event: 'onGetParty',
  277. data: this.party
  278. });
  279. }, this);
  280. },
  281. declineInvite: function (msg) {
  282. let targetId = msg.data.targetId;
  283. let target = cons.players.find(c => c.id === targetId);
  284. if (!target)
  285. return;
  286. this.sendMessage(target.name + ' declined your party invitation', 'color-redA');
  287. },
  288. //Gets called on the player that requested to leave
  289. leaveParty: function (msg) {
  290. let name = this.obj.name;
  291. this.party.spliceWhere(p => p === this.obj.id);
  292. this.party.forEach(function (p) {
  293. let player = cons.players.find(c => c.id === p);
  294. let messages = [{
  295. class: 'q0',
  296. message: name + ' has left the party'
  297. }];
  298. let party = this.party;
  299. if (this.party.length === 1) {
  300. messages.push({
  301. class: 'q0',
  302. message: 'your group has been disbanded'
  303. });
  304. player.social.isPartyLeader = false;
  305. player.social.party = null;
  306. player.social.updateMainThread('party', player.social.party);
  307. party = null;
  308. }
  309. player.socket.emit('events', {
  310. onGetParty: [party],
  311. onGetMessages: [{
  312. messages: messages
  313. }]
  314. });
  315. }, this);
  316. this.obj.socket.emit('events', {
  317. onGetParty: [
  318. []
  319. ],
  320. onGetMessages: [{
  321. messages: {
  322. class: 'q0',
  323. message: 'you have left the party'
  324. }
  325. }]
  326. });
  327. if ((this.isPartyLeader) && (this.party.length >= 2)) {
  328. let newLeader = cons.players.find(c => c.id === this.party[0]).social;
  329. newLeader.isPartyLeader = true;
  330. this.party.forEach(function (p) {
  331. let returnMsg = newLeader.obj.name + ' is now the party leader';
  332. if (p === newLeader.obj.id)
  333. returnMsg = 'you are now the party leader';
  334. cons.players.find(c => c.id === p).socket.emit('events', {
  335. onGetMessages: [{
  336. messages: [{
  337. class: 'q0',
  338. message: returnMsg
  339. }]
  340. }]
  341. });
  342. }, this);
  343. }
  344. this.party = null;
  345. this.updateMainThread('party', this.party);
  346. },
  347. //Gets called on the player that requested the removal
  348. removeFromParty: function (msg) {
  349. if (!this.isPartyLeader) {
  350. this.sendMessage('you are not the party leader', 'color-redA');
  351. return;
  352. }
  353. let target = cons.players.find(c => c.id === msg.data);
  354. if (!target)
  355. return;
  356. this.party.spliceWhere(p => p === target.id);
  357. this.party.forEach(function (p) {
  358. cons.players.find(c => c.id === p)
  359. .socket.emit('events', {
  360. onGetParty: [this.party],
  361. onGetMessages: [{
  362. messages: [{
  363. class: 'color-yellowB',
  364. message: target.name + ' has been removed from the party'
  365. }]
  366. }]
  367. });
  368. }, this);
  369. target.socket.emit('events', {
  370. onGetMessages: [{
  371. messages: [{
  372. class: 'color-redA',
  373. message: 'you have been removed from the party'
  374. }]
  375. }],
  376. onPartyDisband: [{}]
  377. });
  378. target.social.party = null;
  379. target.social.isPartyLeader = false;
  380. target.social.updateMainThread('party', target.social.party);
  381. if (this.party.length === 1) {
  382. this.party = null;
  383. this.isPartyLeader = null;
  384. this.updateMainThread('party', this.party);
  385. this.sendMessage('your party has been disbanded', 'color-yellowB');
  386. }
  387. },
  388. updateMainThread: function (property, value) {
  389. atlas.updateObject(this.obj, {
  390. components: [{
  391. type: 'social',
  392. [property]: value
  393. }]
  394. });
  395. }
  396. };