package in.twizmwaz.cardinal.module.modules.cores;
import in.twizmwaz.cardinal.GameHandler;
import in.twizmwaz.cardinal.chat.ChatConstant;
import in.twizmwaz.cardinal.chat.LocalizedChatMessage;
import in.twizmwaz.cardinal.chat.UnlocalizedChatMessage;
import in.twizmwaz.cardinal.event.SnowflakeChangeEvent;
import in.twizmwaz.cardinal.event.objective.ObjectiveCompleteEvent;
import in.twizmwaz.cardinal.event.objective.ObjectiveProximityEvent;
import in.twizmwaz.cardinal.event.objective.ObjectiveTouchEvent;
import in.twizmwaz.cardinal.module.GameObjective;
import in.twizmwaz.cardinal.module.Module;
import in.twizmwaz.cardinal.module.modules.chatChannels.TeamChannel;
import in.twizmwaz.cardinal.module.modules.regions.RegionModule;
import in.twizmwaz.cardinal.module.modules.regions.type.BlockRegion;
import in.twizmwaz.cardinal.module.modules.scoreboard.GameObjectiveScoreboardHandler;
import in.twizmwaz.cardinal.module.modules.snowflakes.Snowflakes;
import in.twizmwaz.cardinal.module.modules.team.TeamModule;
import in.twizmwaz.cardinal.module.modules.timeLimit.TimeLimit;
import in.twizmwaz.cardinal.module.modules.tntTracker.TntTracker;
import in.twizmwaz.cardinal.util.ChatUtils;
import in.twizmwaz.cardinal.util.FireworkUtil;
import in.twizmwaz.cardinal.util.MiscUtils;
import in.twizmwaz.cardinal.util.TeamUtils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.HandlerList;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockFormEvent;
import org.bukkit.event.block.BlockFromToEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.util.Vector;
import java.util.*;
public class CoreObjective implements GameObjective {
private final TeamModule team;
private final String name;
private final String id;
private final RegionModule region;
private final int leak;
private final boolean show;
private boolean changesModes;
private double proximity;
private Set<UUID> playersTouched;
private Set<UUID> playersCompleted;
private Material currentType;
private int damageValue;
private Set<Block> lava;
private Set<Block> core;
private boolean touched;
private boolean complete;
private GameObjectiveScoreboardHandler scoreboardHandler;
protected CoreObjective(final TeamModule team, final String name, final String id, final RegionModule region, final int leak, Material type, int damageValue, final boolean show, boolean changesModes) {
this.team = team;
this.name = name;
this.id = id;
this.region = region;
this.leak = leak;
this.damageValue = damageValue;
this.show = show;
this.changesModes = changesModes;
this.proximity = Double.POSITIVE_INFINITY;
this.playersTouched = new HashSet<>();
this.playersCompleted = new HashSet<>();
this.currentType = type;
this.lava = new HashSet<>();
this.core = new HashSet<>();
for (Block block : region.getBlocks()) {
if (partOfObjective(block)) {
core.add(block);
}
if (block.getType().equals(Material.STATIONARY_LAVA) || block.getType().equals(Material.LAVA)) {
lava.add(block);
}
}
this.scoreboardHandler = new GameObjectiveScoreboardHandler(this);
}
@Override
public void unload() {
HandlerList.unregisterAll(this);
}
@Override
public TeamModule getTeam() {
return team;
}
@Override
public String getName() {
return name;
}
@Override
public String getId() {
return id;
}
@Override
public boolean isTouched() {
return touched;
}
@Override
public boolean isComplete() {
return complete;
}
@Override
public boolean showOnScoreboard() {
return show;
}
@Override
public GameObjectiveScoreboardHandler getScoreboardHandler() {
return scoreboardHandler;
}
@EventHandler
public void onObsidianForm(BlockFormEvent event) {
if (this.lava.contains(event.getBlock())) {
if (event.getNewState().getType().equals(Material.OBSIDIAN)) {
event.setCancelled(true);
}
}
}
@EventHandler
public void onBlockPlace(BlockPlaceEvent event) {
if (lava.contains(event.getBlock())) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onBlockBreak(BlockBreakEvent event) {
if (!event.isCancelled()) {
if (getBlocks().contains(event.getBlock())) {
if (TeamUtils.getTeamByPlayer(event.getPlayer()) != team) {
boolean touchMessage = false;
if (!playersTouched.contains(event.getPlayer().getUniqueId())) {
playersTouched.add(event.getPlayer().getUniqueId());
TeamModule teamModule = TeamUtils.getTeamByPlayer(event.getPlayer());
TeamChannel channel = TeamUtils.getTeamChannel(teamModule);
if (this.show && !this.complete) {
channel.sendLocalizedMessage(new LocalizedChatMessage(ChatConstant.UI_OBJECTIVE_TOUCHED, teamModule.getColor() + event.getPlayer().getName() + ChatColor.GRAY, ChatColor.RED + name + ChatColor.GRAY));
for (Player player : Bukkit.getOnlinePlayers()) {
if (TeamUtils.getTeamByPlayer(player) != null && TeamUtils.getTeamByPlayer(player).isObserver()) {
String message = new LocalizedChatMessage(ChatConstant.UI_OBJECTIVE_DAMAGED_FOR, teamModule.getColor() + event.getPlayer().getName() + ChatColor.GRAY, ChatColor.AQUA + name + ChatColor.GRAY, teamModule.getCompleteName() + ChatColor.GRAY).getMessage(player.getLocale());
if (!teamModule.getOriginalName().equalsIgnoreCase(teamModule.getName())) {
message = message.replace(new LocalizedChatMessage(ChatConstant.MISC_THE).getMessage(player.getLocale()) + " ", "");
}
player.sendMessage(message);
}
}
touchMessage = true;
}
}
if (!playersCompleted.contains(event.getPlayer().getUniqueId())) playersCompleted.add(event.getPlayer().getUniqueId());
boolean oldState = this.touched;
this.touched = true;
ObjectiveTouchEvent touchEvent = new ObjectiveTouchEvent(this, event.getPlayer(), !oldState, touchMessage);
Bukkit.getServer().getPluginManager().callEvent(touchEvent);
event.setCancelled(false);
} else {
event.setCancelled(true);
if (this.show) ChatUtils.sendWarningMessage(event.getPlayer(), new LocalizedChatMessage(ChatConstant.ERROR_OWN_CORE));
return;
}
}
if (core.contains(event.getBlock())) {
if (TeamUtils.getTeamByPlayer(event.getPlayer()) == team) {
event.setCancelled(true);
if (this.show) ChatUtils.sendWarningMessage(event.getPlayer(), new LocalizedChatMessage(ChatConstant.ERROR_OWN_CORE));
}
}
}
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onEntityExplode(EntityExplodeEvent event) {
if (!event.isCancelled()) {
List<Block> objectiveBlownUp = new ArrayList<>();
for (Block block : event.blockList()) {
if (getBlocks().contains(block) || core.contains(block)) {
objectiveBlownUp.add(block);
}
}
boolean oldState = this.touched;
boolean blownUp = false;
Player eventPlayer = null;
boolean touchMessage = false;
for (Block block : objectiveBlownUp) {
if (TntTracker.getWhoPlaced(event.getEntity()) != null) {
UUID player = TntTracker.getWhoPlaced(event.getEntity());
if (Bukkit.getOfflinePlayer(player).isOnline()) {
if (TeamUtils.getTeamByPlayer(Bukkit.getPlayer(player)) == team) {
event.blockList().remove(block);
} else {
if (!playersTouched.contains(player)) {
playersTouched.add(player);
TeamModule teamModule = TeamUtils.getTeamByPlayer(Bukkit.getPlayer(player));
TeamChannel channel = TeamUtils.getTeamChannel(teamModule);
if (this.show && !this.complete) {
channel.sendLocalizedMessage(new LocalizedChatMessage(ChatConstant.UI_OBJECTIVE_TOUCHED, teamModule.getColor() + Bukkit.getPlayer(player).getName() + ChatColor.GRAY, ChatColor.RED + name + ChatColor.GRAY));
for (Player player1 : Bukkit.getOnlinePlayers()) {
if (TeamUtils.getTeamByPlayer(player1) != null && TeamUtils.getTeamByPlayer(player1).isObserver()) {
player1.sendMessage(new LocalizedChatMessage(ChatConstant.UI_OBJECTIVE_TOUCHED_FOR, teamModule.getColor() + Bukkit.getPlayer(player).getName() + ChatColor.GRAY, ChatColor.RED + name + ChatColor.GRAY, teamModule.getCompleteName() + ChatColor.GRAY).getMessage(player1.getLocale()));
}
}
touchMessage = true;
}
}
if (!playersCompleted.contains(Bukkit.getPlayer(player).getUniqueId())) playersCompleted.add(Bukkit.getPlayer(player).getUniqueId());
this.touched = true;
blownUp = true;
eventPlayer = Bukkit.getPlayer(player);
}
} else {
if (!playersTouched.contains(player)) {
playersTouched.add(player);
}
this.touched = true;
blownUp = true;
}
} else {
this.touched = true;
blownUp = true;
}
}
if (!this.complete && blownUp) {
ObjectiveTouchEvent touchEvent = new ObjectiveTouchEvent(this, eventPlayer, !oldState, touchMessage);
Bukkit.getServer().getPluginManager().callEvent(touchEvent);
}
}
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onBlockFromTo(BlockFromToEvent event) {
if (!event.isCancelled()) {
Block to = event.getToBlock();
Block from = event.getBlock();
if (CoreObjective.getClosestCore(to.getX(), to.getY(), to.getZ()).equals(this)) {
if ((from.getType().equals(Material.LAVA) || from.getType().equals(Material.STATIONARY_LAVA)) && to.getType().equals(Material.AIR)) {
double minY = 256;
for (Block block : getBlocks()) {
if (block.getY() < minY)
minY = block.getY();
}
if (minY - to.getY() >= leak && !this.complete) {
this.complete = true;
event.setCancelled(false);
if (this.show) ChatUtils.getGlobalChannel().sendLocalizedMessage(new UnlocalizedChatMessage(ChatColor.RED + "{0}", new LocalizedChatMessage(ChatConstant.UI_OBJECTIVE_LEAKED, team.getCompleteName() + ChatColor.RED, ChatColor.DARK_AQUA + name + ChatColor.RED)));
FireworkUtil.spawnFirework(event.getBlock().getLocation(), event.getBlock().getWorld(), MiscUtils.convertChatColorToColor(team.getColor()));
ObjectiveCompleteEvent compEvent = new ObjectiveCompleteEvent(this, null);
Bukkit.getServer().getPluginManager().callEvent(compEvent);
}
}
}
}
}
@EventHandler
public void onPlayerDeath(PlayerDeathEvent event) {
while (playersTouched.contains(event.getEntity().getUniqueId())) {
playersTouched.remove(event.getEntity().getUniqueId());
}
}
public RegionModule getRegion() {
return region;
}
public Set<Block> getCore() {
return core;
}
public boolean partOfObjective(Block block) {
return currentType.equals(block.getType()) && (damageValue == -1 || damageValue == (int) block.getState().getData().getData());
}
public List<Block> getBlocks() {
List<Block> blocks = new ArrayList<>();
for (Block block : region.getBlocks()) {
if (partOfObjective(block)) {
blocks.add(block);
}
}
return blocks;
}
public static CoreObjective getClosestCore(double x, double y, double z) {
CoreObjective core = null;
double closestDistance = Double.POSITIVE_INFINITY;
for (Module module : GameHandler.getGameHandler().getMatch().getModules()) {
if (module instanceof CoreObjective) {
BlockRegion center = ((CoreObjective) module).getRegion().getCenterBlock();
if (new Vector(x, y, z).distance(new Vector(center.getX(), center.getY(), center.getZ())) < closestDistance) {
core = (CoreObjective) module;
closestDistance = new Vector(x, y, z).distance(new Vector(center.getX(), center.getY(), center.getZ()));
}
}
}
return core;
}
public boolean showProximity() {
return GameHandler.getGameHandler().getMatch().getModules().getModule(TimeLimit.class).getTimeLimit() != 0 && GameHandler.getGameHandler().getMatch().getModules().getModule(TimeLimit.class).getResult().equals(TimeLimit.Result.MOST_OBJECTIVES);
}
public boolean changesModes() {
return changesModes;
}
public void setChangesModes(boolean changesModes) {
this.changesModes = changesModes;
}
public void setMaterial(Material material, int damageValue) {
this.currentType = material;
this.damageValue = damageValue;
}
@EventHandler
public void onPlayerMove(PlayerMoveEvent event) {
if (GameHandler.getGameHandler().getMatch().isRunning() && !this.touched && TeamUtils.getTeamByPlayer(event.getPlayer()) != null && !TeamUtils.getTeamByPlayer(event.getPlayer()).isObserver() && TeamUtils.getTeamByPlayer(event.getPlayer()) != this.team) {
if (event.getPlayer().getLocation().toVector().distance(region.getCenterBlock().getVector()) < proximity) {
double old = proximity;
proximity = event.getPlayer().getLocation().toVector().distance(region.getCenterBlock().getVector());
Bukkit.getServer().getPluginManager().callEvent(new ObjectiveProximityEvent(this, event.getPlayer(), old, proximity));
}
}
}
public double getProximity() {
return proximity;
}
@EventHandler
public void onCoreLeak(ObjectiveCompleteEvent event) {
if (event.getObjective().equals(this) && event.getObjective().showOnScoreboard()) {
for (UUID player : playersCompleted) {
if (Bukkit.getOfflinePlayer(player).isOnline()) {
Bukkit.getServer().getPluginManager().callEvent(new SnowflakeChangeEvent(Bukkit.getPlayer(player), Snowflakes.ChangeReason.CORE_LEAK, 15, ChatColor.RED + name + ChatColor.GRAY));
}
}
}
}
}