Source: hg/actions/SendEventMessageAction.js

// Copyright 2019 Campbell Crowley. All rights reserved.
// Author: Campbell Crowley (dev@campbellcrowley.com)
const ChannelAction = require('./ChannelAction.js');
const Jimp = require('jimp');

/**
 * @description Sends the current event message.
 *
 * @memberof HungryGames~Action
 * @inner
 * @augments HungryGames~Action~ChannelAction
 */
class SendEventMessageAction extends ChannelAction {
  /**
   * @description Create an action that will send a message to the game channel
   * showing the event that occurred.
   */
  constructor() {
    super((hg, game, channel) => {
      const index = game.currentGame.day.state - 2;
      const events = game.currentGame.day.events;
      const evt = events[index];
      if (!evt) {
        hg._parent.error(
            'Attempted to print event beyond end of list. ' + index + '/' +
            events.length + ' (' + game.id + ')');
        game.clearIntervals();
        game.currentGame.isPaused = true;
      } else if (evt.battle && evt.state < evt.attacks.length) {
        const attk = evt.attacks[evt.state];
        const embed = new hg._parent.Discord.EmbedBuilder();
        const message = attk.message.split('\n');
        embed.addFields([{name: message[1], value: message[2]}]);
        embed.setColor([50, 0, 0]);

        const avatarSizes = game.options.battleAvatarSizes;
        const battleIconSize = avatarSizes.avatar;
        if (battleIconSize === 0 || attk.icons.length === 0) {
          // Send without image.
          if (!game.options.disableOutput) {
            channel.send({content: message[0], embeds: [embed]})
                .catch((err) => {
                  hg._parent.error(
                      'Failed to send battle event message without image: ' +
                      channel.id);
                  console.error(err);
                });
          }
        } else {
          const iconGap = avatarSizes.gap;
          const underlineSize = avatarSizes.underline;

          // Create image, then send.
          const finalImage = new Jimp(
              attk.icons.length * (battleIconSize + iconGap) - iconGap,
              battleIconSize + underlineSize * 2);
          let responses = 0;
          const newImage = function(image, outcome, placement, barColor) {
            try {
              if (battleIconSize > 0) {
                if (image) image.resize(battleIconSize, battleIconSize);
                if (underlineSize > 0) {
                  if (typeof barColor === 'number') {
                    finalImage.blit(
                        new Jimp(battleIconSize, underlineSize, barColor),
                        placement * (battleIconSize + iconGap), 0);
                  }
                  if (outcome == 'dies') {
                    finalImage.blit(
                        new Jimp(battleIconSize, underlineSize, 0xFF0000FF),
                        placement * (battleIconSize + iconGap),
                        battleIconSize + underlineSize);
                  } else if (outcome == 'wounded') {
                    finalImage.blit(
                        new Jimp(battleIconSize, underlineSize, 0xFFFF00FF),
                        placement * (battleIconSize + iconGap),
                        battleIconSize + underlineSize);
                  }
                }
                if (image) {
                  finalImage.blit(
                      image, placement * (battleIconSize + iconGap),
                      underlineSize);
                }
              }
            } catch (err) {
              console.error(err);
            }
            responses++;
            if (responses == attk.icons.length) {
              finalImage.getBuffer(Jimp.MIME_PNG, function(err, out) {
                // Attach file, then send.
                if (!game.options.disableOutput) {
                  channel
                      .send({
                        content: message[0],
                        embeds: [embed],
                        files: [new hg._parent.Discord.AttachmentBuilder(
                            out, {name: 'hgBattle.png'})],
                      })
                      .catch((err) => {
                        hg._parent.error(
                            'Failed to send battle event message with image: ' +
                            channel.id);
                        console.error(err);
                      });
                }
              });
            }
          };
          let numNonUser = 0;
          for (let i = 0; i < attk.icons.length; i++) {
            let outcome = attk.victim.outcome;
            if (!attk.icons[i].id) {
              numNonUser++;
              outcome = 'nothing';
            } else if (i >= attk.victim.count + numNonUser) {
              outcome = attk.attacker.outcome;
            }
            hg._parent.readImage(attk.icons[i].url)
                .then(function(outcome, placement, settings) {
                  return function(image) {
                    newImage(
                        image, outcome, placement,
                        settings && settings['hg:bar_color']);
                  };
                }(outcome, i, attk.icons[i].settings))
                .catch((err) => {
                  hg._parent.error('Failed to read image');
                  console.log(err);
                  responses++;
                });
          }
        }
      } else {
        const avatarSizes = game.options.eventAvatarSizes;
        const iconSize = avatarSizes.avatar;
        if (iconSize == 0 || evt.icons.length === 0) {
          if (!game.options.disableOutput) {
            channel
                .send({
                  content: (evt.mentionString || '') + evt.message + '\n' +
                      (evt.subMessage || ''),
                })
                .catch((err) => {
                  hg._parent.error(
                      'Failed to send message without image: ' + channel.id);
                  console.error(err);
                });
          }
        } else {
          const iconGap = avatarSizes.gap;
          const underlineSize = avatarSizes.underline;
          const embed = new hg._parent.Discord.EmbedBuilder();
          if (evt.subMessage) {
            embed.setDescription(`${evt.message}\n${evt.subMessage}`);
          } else {
            embed.setDescription(evt.message);
          }
          embed.setColor([125, 0, 0]);
          const finalImage = new Jimp(
              evt.icons.length * (iconSize + iconGap) - iconGap,
              iconSize + underlineSize * 2);
          let responses = 0;
          const newImage = function(image, outcome, placement, barColor) {
            try {
              if (iconSize > 0) {
                if (image) image.resize(iconSize, iconSize);
                if (underlineSize > 0) {
                  if (typeof barColor === 'number') {
                    finalImage.blit(
                        new Jimp(iconSize, underlineSize, barColor),
                        placement * (iconSize + iconGap), 0);
                  }
                  if (outcome == 'dies') {
                    finalImage.blit(
                        new Jimp(iconSize, underlineSize, 0xFF0000FF),
                        placement * (iconSize + iconGap),
                        iconSize + underlineSize);
                  } else if (outcome == 'wounded') {
                    finalImage.blit(
                        new Jimp(iconSize, underlineSize, 0xFFFF00FF),
                        placement * (iconSize + iconGap),
                        iconSize + underlineSize);
                  } else if (outcome == 'thrives') {
                    finalImage.blit(
                        new Jimp(iconSize, underlineSize, 0x00FF00FF),
                        placement * (iconSize + iconGap),
                        iconSize + underlineSize);
                  } else if (outcome == 'revived') {
                    finalImage.blit(
                        new Jimp(iconSize, underlineSize, 0x00FFFFFF),
                        placement * (iconSize + iconGap),
                        iconSize + underlineSize);
                  }
                }
                if (image) {
                  finalImage.blit(
                      image, placement * (iconSize + iconGap), underlineSize);
                }
              }
            } catch (err) {
              console.error(err);
            }
            responses++;
            if (responses == evt.icons.length) {
              finalImage.getBuffer(Jimp.MIME_PNG, (err, out) => {
                if (!game.options.disableOutput) {
                  channel
                      .send({
                        content: evt.mentionString || '\u200B',
                        embeds: [embed],
                        files: [new hg._parent.Discord.AttachmentBuilder(
                            out, {name: 'hgEvent.png'})],
                      })
                      .catch((err) => {
                        hg._parent.error(
                            'Failed to send message with image: ' + channel.id);
                        console.error(err);
                      });
                }
              });
            }
          };
          let numNonUser = 0;
          for (let i = 0; i < evt.icons.length; i++) {
            let outcome = evt.victim.outcome;
            if (!evt.icons[i].id) {
              numNonUser++;
              outcome = 'nothing';
            } else if (i >= evt.victim.count + numNonUser) {
              outcome = evt.attacker.outcome;
            }
            hg._parent.readImage(evt.icons[i].url)
                .then(function(outcome, placement, settings) {
                  return function(image) {
                    newImage(
                        image, outcome, placement,
                        settings && settings['hg:bar_color']);
                  };
                }(outcome, evt.icons.length - i - 1, evt.icons[i].settings))
                .catch(function(err) {
                  hg._parent.error('Failed to read image');
                  console.log(err);
                  responses++;
                });
          }
        }
      }
    });
  }
  /**
   * @description Create action from save data.
   * @public
   * @static
   * @override
   * @returns {HungryGames~SendEventMessageAction} The created action.
   */
  static create() {
    return new SendEventMessageAction();
  }
}

module.exports = SendEventMessageAction;