You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

474 lines
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-tealC',
  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. sendPrivateMessage: function (messageString) {
  122. let playerName = '';
  123. //Check if there's a space in the name
  124. if (messageString[1] === "'") {
  125. playerName = messageString.substring(2, messageString.indexOf("'", 2));
  126. messageString = messageString.replace("@'" + playerName + "' ", '');
  127. } else {
  128. playerName = messageString.substring(1, messageString.indexOf(' '));
  129. messageString = messageString.replace('@' + playerName + ' ', '');
  130. }
  131. if (playerName === this.obj.name)
  132. return;
  133. let target = cons.players.find(p => p.name === playerName);
  134. if (!target)
  135. return;
  136. this.obj.socket.emit('event', {
  137. event: 'onGetMessages',
  138. data: {
  139. messages: [{
  140. class: 'color-yellowB',
  141. message: '(you to ' + playerName + '): ' + messageString,
  142. type: 'chat',
  143. source: this.obj.name
  144. }]
  145. }
  146. });
  147. target.socket.emit('event', {
  148. event: 'onGetMessages',
  149. data: {
  150. messages: [{
  151. class: 'color-yellowB',
  152. message: '(' + this.obj.name + ' to you): ' + messageString,
  153. type: 'chat',
  154. source: this.obj.name
  155. }]
  156. }
  157. });
  158. },
  159. chat: function (msg) {
  160. if (!msg.data.message)
  161. return;
  162. msg.data.message = msg.data.message
  163. .split('<')
  164. .join('&lt;')
  165. .split('>')
  166. .join('&gt;');
  167. if (!msg.data.message)
  168. return;
  169. if (msg.data.message.trim() === '')
  170. return;
  171. if (this.muted) {
  172. this.sendMessage('You have been muted from talking', 'color-redA');
  173. return;
  174. }
  175. let messageString = msg.data.message;
  176. if (messageString.length > this.maxChatLength)
  177. return;
  178. let history = this.messageHistory;
  179. let time = +new Date();
  180. history.spliceWhere(h => ((time - h.time) > 5000));
  181. if (history.length > 0) {
  182. if (history[history.length - 1].msg === messageString) {
  183. this.sendMessage('You have already sent that message', 'color-redA');
  184. return;
  185. } else if (history.length >= 3) {
  186. this.sendMessage('You are sending too many messages', 'color-redA');
  187. return;
  188. }
  189. }
  190. this.onBeforeChat(msg.data);
  191. if (msg.data.ignore)
  192. return;
  193. if (!msg.data.item && !profanities.isClean(messageString)) {
  194. this.sendMessage('Profanities detected in message. Blocked.', 'color-redA');
  195. return;
  196. }
  197. history.push({
  198. msg: messageString,
  199. time: time
  200. });
  201. let charname = this.obj.auth.charname;
  202. let msgStyle = roles.getRoleMessageStyle(this.obj) || ('color-grayB');
  203. let msgEvent = {
  204. source: charname,
  205. msg: messageString
  206. };
  207. events.emit('onBeforeSendMessage', msgEvent);
  208. messageString = msgEvent.msg;
  209. if (messageString[0] === '@')
  210. this.sendPrivateMessage(messageString);
  211. else if (messageString[0] === '$')
  212. this.sendCustomChannelMessage(msg);
  213. else if (messageString[0] === '%')
  214. this.sendPartyMessage(msg);
  215. else {
  216. let prefix = roles.getRoleMessagePrefix(this.obj) || '';
  217. cons.emit('event', {
  218. event: 'onGetMessages',
  219. data: {
  220. messages: [{
  221. class: msgStyle,
  222. message: prefix + charname + ': ' + msg.data.message,
  223. item: msg.data.item,
  224. type: 'chat',
  225. source: this.obj.name
  226. }]
  227. }
  228. });
  229. }
  230. },
  231. dc: function () {
  232. if (!this.party)
  233. return;
  234. this.leaveParty();
  235. },
  236. //This gets called on the target player
  237. getInvite: function (msg) {
  238. if (this.party)
  239. return;
  240. let obj = this.obj;
  241. let sourceId = msg.data.sourceId;
  242. if (sourceId === obj.id)
  243. return;
  244. let source = cons.players.find(c => c.id === sourceId);
  245. if (!source)
  246. return;
  247. source.social.sendMessage('invite sent', 'color-yellowB');
  248. this.sendMessage(source.name + ' has invited you to join a party', 'color-yellowB');
  249. this.obj.socket.emit('event', {
  250. event: 'onGetInvite',
  251. data: sourceId
  252. });
  253. },
  254. //This gets called on the player that initiated the invite
  255. acceptInvite: function (msg) {
  256. let sourceId = msg.data.sourceId;
  257. let source = cons.players.find(c => c.id === sourceId);
  258. if (!source)
  259. return;
  260. if (!this.party) {
  261. this.isPartyLeader = true;
  262. this.party = [this.obj.id];
  263. this.updateMainThread('party', this.party);
  264. }
  265. // Only add if not yet in party
  266. if (!this.party.find(id => (id === sourceId)))
  267. this.party.push(sourceId);
  268. this.updateMainThread('party', this.party);
  269. this.party.forEach(function (p) {
  270. let player = cons.players.find(c => c.id === p);
  271. player.social.party = this.party;
  272. player.social.updateMainThread('party', player.social.party);
  273. let returnMsg = source.name + ' has joined the party';
  274. if (p === sourceId)
  275. returnMsg = 'you have joined a party';
  276. player.social.sendMessage(returnMsg, 'color-yellowB');
  277. player
  278. .socket.emit('event', {
  279. event: 'onGetParty',
  280. data: this.party
  281. });
  282. }, this);
  283. },
  284. declineInvite: function (msg) {
  285. let targetId = msg.data.targetId;
  286. let target = cons.players.find(c => c.id === targetId);
  287. if (!target)
  288. return;
  289. this.sendMessage(target.name + ' declined your party invitation', 'color-redA');
  290. },
  291. //Gets called on the player that requested to leave
  292. leaveParty: function (msg) {
  293. let name = this.obj.name;
  294. this.party.spliceWhere(p => p === this.obj.id);
  295. this.party.forEach(function (p) {
  296. let player = cons.players.find(c => c.id === p);
  297. let messages = [{
  298. class: 'q0',
  299. message: name + ' has left the party'
  300. }];
  301. let party = this.party;
  302. if (this.party.length === 1) {
  303. messages.push({
  304. class: 'q0',
  305. message: 'your group has been disbanded'
  306. });
  307. player.social.isPartyLeader = false;
  308. player.social.party = null;
  309. player.social.updateMainThread('party', player.social.party);
  310. party = null;
  311. }
  312. player.socket.emit('events', {
  313. onGetParty: [party],
  314. onGetMessages: [{
  315. messages: messages
  316. }]
  317. });
  318. }, this);
  319. this.obj.socket.emit('events', {
  320. onGetParty: [
  321. []
  322. ],
  323. onGetMessages: [{
  324. messages: {
  325. class: 'q0',
  326. message: 'you have left the party'
  327. }
  328. }]
  329. });
  330. if ((this.isPartyLeader) && (this.party.length >= 2)) {
  331. let newLeader = cons.players.find(c => c.id === this.party[0]).social;
  332. newLeader.isPartyLeader = true;
  333. this.party.forEach(function (p) {
  334. let returnMsg = newLeader.obj.name + ' is now the party leader';
  335. if (p === newLeader.obj.id)
  336. returnMsg = 'you are now the party leader';
  337. cons.players.find(c => c.id === p).socket.emit('events', {
  338. onGetMessages: [{
  339. messages: [{
  340. class: 'q0',
  341. message: returnMsg
  342. }]
  343. }]
  344. });
  345. }, this);
  346. }
  347. this.party = null;
  348. this.updateMainThread('party', this.party);
  349. },
  350. //Gets called on the player that requested the removal
  351. removeFromParty: function (msg) {
  352. if (!this.isPartyLeader) {
  353. this.sendMessage('you are not the party leader', 'color-redA');
  354. return;
  355. }
  356. let target = cons.players.find(c => c.id === msg.data);
  357. if (!target)
  358. return;
  359. this.party.spliceWhere(p => p === target.id);
  360. this.party.forEach(function (p) {
  361. cons.players.find(c => c.id === p)
  362. .socket.emit('events', {
  363. onGetParty: [this.party],
  364. onGetMessages: [{
  365. messages: [{
  366. class: 'color-yellowB',
  367. message: target.name + ' has been removed from the party'
  368. }]
  369. }]
  370. });
  371. }, this);
  372. target.socket.emit('events', {
  373. onGetMessages: [{
  374. messages: [{
  375. class: 'color-redA',
  376. message: 'you have been removed from the party'
  377. }]
  378. }],
  379. onPartyDisband: [{}]
  380. });
  381. target.social.party = null;
  382. target.social.isPartyLeader = false;
  383. target.social.updateMainThread('party', target.social.party);
  384. if (this.party.length === 1) {
  385. this.party = null;
  386. this.isPartyLeader = null;
  387. this.updateMainThread('party', this.party);
  388. this.sendMessage('your party has been disbanded', 'color-yellowB');
  389. }
  390. },
  391. updateMainThread: function (property, value) {
  392. atlas.updateObject(this.obj, {
  393. components: [{
  394. type: 'social',
  395. [property]: value
  396. }]
  397. });
  398. }
  399. };