content: /*
   * BedWars1058 - A bed wars mini-game.
   * Copyright (C) 2021 Andrei Dascălu
   *
   * This program is free software: you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation, either version 3 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program.  If not, see <https://www.gnu.org/licenses/>.
   *
   * Contact e-mail: andrew.dascalu@gmail.com
   */
  
  package com.andrei1058.bedwars.support.version.v1_12_R1;
  
  import com.andrei1058.bedwars.api.arena.team.ITeam;
  import com.andrei1058.bedwars.api.language.Language;
  import com.andrei1058.bedwars.api.language.Messages;
  import com.andrei1058.bedwars.support.version.common.VersionCommon;
  import com.google.common.collect.Sets;
  import net.minecraft.server.v1_12_R1.*;
  import org.apache.commons.lang.StringUtils;
  import org.bukkit.Location;
  import org.bukkit.craftbukkit.v1_12_R1.CraftWorld;
  import org.bukkit.craftbukkit.v1_12_R1.entity.CraftLivingEntity;
  import org.bukkit.craftbukkit.v1_12_R1.event.CraftEventFactory;
  import org.bukkit.entity.LivingEntity;
  import org.bukkit.event.entity.CreatureSpawnEvent;
  
  import java.lang.reflect.Field;
  import java.util.Random;
  
  @SuppressWarnings("ALL")
  public class Silverfish extends EntitySilverfish {
  
      private ITeam team;
  
      @SuppressWarnings("WeakerAccess")
      public Silverfish(World world, ITeam team) {
          super(world);
          try {
              Field bField = PathfinderGoalSelector.class.getDeclaredField("b");
              bField.setAccessible(true);
              Field cField = PathfinderGoalSelector.class.getDeclaredField("c");
              cField.setAccessible(true);
              bField.set(this.goalSelector, Sets.newLinkedHashSet());
              bField.set(this.targetSelector, Sets.newLinkedHashSet());
              cField.set(this.goalSelector, Sets.newLinkedHashSet());
              cField.set(this.targetSelector, Sets.newLinkedHashSet());
          } catch (IllegalAccessException | NoSuchFieldException e1) {
              e1.printStackTrace();
          }
          this.team = team;
          this.goalSelector.a(1, new PathfinderGoalFloat(this));
          this.goalSelector.a(2, new PathfinderGoalMeleeAttack(this,1.9D, false));
          this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this, true));
          this.goalSelector.a(3, new PathfinderGoalRandomStroll(this, 2D));
          this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget(this, EntityHuman.class, 20, true, false, player -> {
              return ((EntityHuman)player).isAlive() && !team.wasMember(((EntityHuman)player).getUniqueID()) && !team.getArena().isReSpawning(((EntityHuman)player).getUniqueID())
                      && !team.getArena().isSpectator(((EntityHuman)player).getUniqueID());
          }));
          this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget(this, IGolem.class, 20, true, false, golem -> {
              return ((IGolem)golem).getTeam() != team;
          }));
          this.targetSelector.a(4, new PathfinderGoalNearestAttackableTarget(this, Silverfish.class, 20, true, false, sf -> {
              return ((Silverfish)sf).getTeam() != team;
          }));
      }
  
      public ITeam getTeam() {
          return team;
      }
  
      @SuppressWarnings("WeakerAccess")
      static class PathfinderGoalSilverfishHideInBlock extends PathfinderGoalRandomStroll {
          private EnumDirection h;
          private boolean i;
  
          public PathfinderGoalSilverfishHideInBlock(EntitySilverfish entitysilverfish) {
              super(entitysilverfish, 1.0D, 10);
              this.a(1);
          }
  
          public boolean a() {
              if (this.a.getGoalTarget() != null) {
                  return false;
              } else if (!this.a.getNavigation().o()) {
                  return false;
              } else {
                  Random random = this.a.getRandom();
                  if (this.a.world.getGameRules().getBoolean("mobGriefing") && random.nextInt(10) == 0) {
                      this.h = EnumDirection.a(random);
                      BlockPosition blockposition = (new BlockPosition(this.a.locX, this.a.locY + 0.5D, this.a.locZ)).shift(this.h);
                      IBlockData iblockdata = this.a.world.getType(blockposition);
                      if (BlockMonsterEggs.x(iblockdata)) {
                          this.i = true;
                          return true;
                      }
                  }
  
                  this.i = false;
                  return super.a();
              }
          }
  
          public boolean b() {
              return !this.i && super.b();
          }
  
          public void c() {
              if (!this.i) {
                  super.c();
              } else {
                  World world = this.a.world;
                  BlockPosition blockposition = (new BlockPosition(this.a.locX, this.a.locY + 0.5D, this.a.locZ)).shift(this.h);
                  IBlockData iblockdata = world.getType(blockposition);
                  if (BlockMonsterEggs.x(iblockdata)) {
                      if (CraftEventFactory.callEntityChangeBlockEvent(this.a, blockposition, Blocks.MONSTER_EGG, Block.getId(BlockMonsterEggs.getById(iblockdata.getBlock().toLegacyData(iblockdata)))).isCancelled()) {
                          return;
                      }
  
                      world.setTypeAndData(blockposition, Blocks.MONSTER_EGG.getBlockData().set(BlockMonsterEggs.VARIANT, BlockMonsterEggs.EnumMonsterEggVarient.a(iblockdata)), 3);
                      this.a.doSpawnEffect();
                      this.a.die();
                  }
              }
  
          }
      }
  
      public static LivingEntity spawn(Location loc, ITeam team, double speed, double health, int despawn, double damage) {
          WorldServer mcWorld = ((CraftWorld)loc.getWorld()).getHandle();
          Silverfish customEnt = new Silverfish(mcWorld, team);
          customEnt.setLocation(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch());
          customEnt.getAttributeInstance(GenericAttributes.maxHealth).setValue(health);
          customEnt.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).setValue(speed);
          customEnt.getAttributeInstance(GenericAttributes.ATTACK_DAMAGE).setValue(damage);
          ((CraftLivingEntity)customEnt.getBukkitEntity()).setRemoveWhenFarAway(false);
          customEnt.setCustomName(Language.getDefaultLanguage().m(Messages.SHOP_UTILITY_NPC_SILVERFISH_NAME)
                  .replace("{despawn}", String.valueOf(despawn)
                          .replace("{health}", StringUtils.repeat(Language.getDefaultLanguage().m(Messages.FORMATTING_DESPAWNABLE_UTILITY_NPC_HEALTH)+" ", 10))
                          .replace("{TeamColor}", team.getColor().chat().toString())));
          customEnt.setCustomNameVisible(true);
          mcWorld.addEntity(customEnt, CreatureSpawnEvent.SpawnReason.CUSTOM);
          return (LivingEntity) customEnt.getBukkitEntity();
      }
  
      @Override
      public void die() {
          super.die();
          team = null;
          VersionCommon.api.getVersionSupport().getDespawnablesList().remove(this.getUniqueID());
      }
  
      @Override
      public void die(DamageSource damagesource) {
          super.die(damagesource);
          team = null;
          VersionCommon.api.getVersionSupport().getDespawnablesList().remove(this.getUniqueID());
      }
  }
  