package in.twizmwaz.cardinal.module.modules.destroyable; import com.google.common.base.Optional; 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.ObjectiveTouchEvent; import in.twizmwaz.cardinal.module.GameObjective; import in.twizmwaz.cardinal.module.modules.proximity.GameObjectiveProximityHandler; import in.twizmwaz.cardinal.module.modules.regions.RegionModule; 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.ChatUtil; import in.twizmwaz.cardinal.util.Fireworks; import in.twizmwaz.cardinal.util.MiscUtil; import in.twizmwaz.cardinal.util.Teams; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; 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.BlockPistonExtendEvent; import org.bukkit.event.block.BlockPistonRetractEvent; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.entity.EntityExplodeEvent; import org.bukkit.event.entity.PlayerDeathEvent; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.UUID; public class DestroyableObjective implements GameObjective { private final TeamModule team; private final String name; private final String id; private final RegionModule region; private final double completion; private final boolean showPercent; private final boolean repairable; private final boolean show; private final boolean required; private List<Pair<Material, Integer>> materials; private boolean changesModes; private Map<String, GameObjectiveProximityHandler> proximityHandlers; private Set<UUID> playersTouched; private double size; private Map<UUID, Integer> playersCompleted; private List<Block> monument; private double complete; private boolean completed; private GameObjectiveScoreboardHandler scoreboardHandler; protected DestroyableObjective(final TeamModule team, final String name, final String id, final RegionModule region, List<Pair<Material, Integer>> materials, final double completion, final boolean show, final boolean required, boolean changesModes, boolean showPercent, boolean repairable, Map<String, GameObjectiveProximityHandler> proximityHandlers) { this.team = team; this.name = name; this.id = id; this.region = region; this.materials = materials; this.showPercent = showPercent; this.repairable = repairable; this.complete = 0; this.completion = completion; this.show = show; this.required = required; this.changesModes = changesModes; this.completed = false; this.proximityHandlers = proximityHandlers; for (GameObjectiveProximityHandler proximityHandler : proximityHandlers.values()) { proximityHandler.setObjective(this); } this.playersTouched = new HashSet<>(); this.playersCompleted = new HashMap<>(); this.monument = new ArrayList<>(); for (Block block : region.getBlocks()) { if (partOfObjective(block)) { monument.add(block); } } this.size = monument.size(); this.scoreboardHandler = new GameObjectiveScoreboardHandler(this); } @Override public TeamModule getTeam() { return this.team; } @Override public String getName() { return this.name; } @Override public String getId() { return this.id; } @Override public boolean isTouched() { return this.complete > 0; } @Override public boolean isComplete() { return this.completed; } @Override public boolean showOnScoreboard() { return show; } @Override public boolean isRequired() { return required; } @Override public void unload() { HandlerList.unregisterAll(this); } @Override public GameObjectiveScoreboardHandler getScoreboardHandler() { return scoreboardHandler; } @Override public GameObjectiveProximityHandler getProximityHandler(TeamModule team) { return isTouched() || isComplete() ? null : proximityHandlers.get(team.getId()); } @EventHandler(priority = EventPriority.HIGHEST) public void onBlockBreak(BlockBreakEvent event) { if (!event.isCancelled()) { if (getBlocks().contains(event.getBlock())) { Optional<TeamModule> playerTeam = Teams.getTeamByPlayer(event.getPlayer()); if (playerTeam.isPresent() && playerTeam.get() != team) { if (!playersTouched.contains(event.getPlayer().getUniqueId())) { playersTouched.add(event.getPlayer().getUniqueId()); Optional<TeamModule> teamModule = Teams.getTeamByPlayer(event.getPlayer()); if (this.show && !this.completed && teamModule.isPresent()) { Teams.getTeamChannel(teamModule).sendLocalizedMessage(new LocalizedChatMessage(ChatConstant.UI_OBJECTIVE_DAMAGED_FOR, teamModule.get().getColor() + event.getPlayer().getName() + ChatColor.WHITE, name, teamModule.get().getCompleteName() + ChatColor.WHITE)); for (Player player : Bukkit.getOnlinePlayers()) { if (Teams.getTeamByPlayer(player).isPresent() && Teams.getTeamByPlayer(player).get().isObserver()) { player.sendMessage(new LocalizedChatMessage(ChatConstant.UI_OBJECTIVE_DAMAGED_FOR, teamModule.get().getColor() + event.getPlayer().getName() + ChatColor.WHITE, name, teamModule.get().getCompleteName() + ChatColor.WHITE).getMessage(player.getLocale())); } } } } this.complete++; this.playersCompleted.put(event.getPlayer().getUniqueId(), (playersCompleted.containsKey(event.getPlayer().getUniqueId()) ? playersCompleted.get(event.getPlayer().getUniqueId()) + 1 : 1)); if ((this.complete / size) >= this.completion && !this.completed) { this.completed = true; event.setCancelled(false); if (this.show) { for (Player player : Bukkit.getOnlinePlayers()) player.sendMessage(ChatColor.WHITE + new UnlocalizedChatMessage("{0}", new LocalizedChatMessage(ChatConstant.UI_OBJECTIVE_DESTROYED, team.getCompleteName() + ChatColor.WHITE, name, getWhoDestroyed(player.getLocale()))).getMessage(player.getLocale())); } ObjectiveCompleteEvent compEvent = new ObjectiveCompleteEvent(this, event.getPlayer()); Bukkit.getServer().getPluginManager().callEvent(compEvent); } else if (!this.completed) { ObjectiveTouchEvent touchEvent = new ObjectiveTouchEvent(this, event.getPlayer(), false); Bukkit.getServer().getPluginManager().callEvent(touchEvent); } } else { event.setCancelled(true); if (this.show) ChatUtil.sendWarningMessage(event.getPlayer(), new LocalizedChatMessage(ChatConstant.ERROR_OWN_OBJECTIVE)); } } } } @EventHandler(priority = EventPriority.HIGHEST) public void onEntityExplode(EntityExplodeEvent event) { if (!event.isCancelled()) { List<Block> objectiveBlownUp = new ArrayList<>(); for (Block block : event.blockList()) { if (region.contains(block.getLocation()) && partOfObjective(block)) { objectiveBlownUp.add(block); } } boolean blownUp = false; Player eventPlayer = null; boolean touchMessage = false; for (Block block : objectiveBlownUp) { boolean blockDestroyed = false; if (TntTracker.getWhoPlaced(event.getEntity()) != null) { UUID playerID = TntTracker.getWhoPlaced(event.getEntity()); if (Bukkit.getOfflinePlayer(playerID).isOnline()) { Player player = Bukkit.getPlayer(playerID); if (Teams.getTeamByPlayer(Bukkit.getPlayer(playerID)).orNull() == team || (Teams.getTeamByPlayer(Bukkit.getPlayer(playerID)).isPresent() && Teams.getTeamByPlayer(Bukkit.getPlayer(playerID)).get().isObserver())) { event.blockList().remove(block); } else { if (!playersTouched.contains(playerID)) { playersTouched.add(playerID); Optional<TeamModule> teamModule = Teams.getTeamByPlayer(player); if (this.show && !this.completed) { if (!teamModule.isPresent() || !teamModule.get().isObserver()) { Teams.getTeamChannel(teamModule).sendLocalizedMessage(new LocalizedChatMessage(ChatConstant.UI_OBJECTIVE_DAMAGED_FOR, Teams.getTeamColorByPlayer(Bukkit.getPlayer(playerID)) + Bukkit.getPlayer(playerID).getName() + ChatColor.WHITE, name, teamModule.get().getCompleteName() + ChatColor.WHITE)); } for (Player player1 : Bukkit.getOnlinePlayers()) { Optional<TeamModule> team1 = Teams.getTeamByPlayer(player1); if (team1.isPresent() && team1.get().isObserver()) { player1.sendMessage(new LocalizedChatMessage(ChatConstant.UI_OBJECTIVE_DAMAGED_FOR, teamModule.get().getColor() + Bukkit.getPlayer(playerID).getName() + ChatColor.WHITE, name, teamModule.get().getCompleteName() + ChatColor.WHITE).getMessage(player1.getLocale())); } } touchMessage = true; } } blockDestroyed = true; blownUp = true; eventPlayer = Bukkit.getPlayer(playerID); } } else { if (!playersTouched.contains(playerID)) { playersTouched.add(playerID); } blockDestroyed = true; blownUp = true; } } else { blockDestroyed = true; blownUp = true; } if (blockDestroyed) { this.complete++; if (eventPlayer != null) this.playersCompleted.put(eventPlayer.getUniqueId(), (playersCompleted.containsKey(eventPlayer.getUniqueId()) ? playersCompleted.get(eventPlayer.getUniqueId()) + 1 : 1)); } } if (blownUp) { if ((this.complete / size) >= this.completion && !this.completed) { this.completed = true; if (this.show) { for (Player player : Bukkit.getOnlinePlayers()) player.sendMessage(ChatColor.WHITE + new UnlocalizedChatMessage("{0}", new LocalizedChatMessage(ChatConstant.UI_OBJECTIVE_DESTROYED, team.getCompleteName() + ChatColor.WHITE, name, getWhoDestroyed(player.getLocale()))).getMessage(player.getLocale())); Bukkit.getConsoleSender().sendMessage(ChatColor.WHITE + new UnlocalizedChatMessage("{0}", new LocalizedChatMessage(ChatConstant.UI_OBJECTIVE_DESTROYED, team.getCompleteName() + ChatColor.WHITE, name, getWhoDestroyed(Locale.getDefault().toString()))).getMessage(Locale.getDefault().toString())); } ObjectiveCompleteEvent compEvent = new ObjectiveCompleteEvent(this, eventPlayer); Bukkit.getServer().getPluginManager().callEvent(compEvent); } if (!this.completed) { ObjectiveTouchEvent touchEvent = new ObjectiveTouchEvent(this, eventPlayer, touchMessage); Bukkit.getServer().getPluginManager().callEvent(touchEvent); } } } } @EventHandler public void onBlockPlace(BlockPlaceEvent event) { if (!isComplete()) { if (monument.contains(event.getBlock()) && partOfObjective(event.getBlockPlaced())) { if (Teams.getTeamByPlayer(event.getPlayer()).orNull() != team) { ChatUtil.sendWarningMessage(event.getPlayer(), new LocalizedChatMessage(ChatConstant.ERROR_ENEMY_OBJECTIVE)); event.setCancelled(true); } else if (!isRepairable()) { ChatUtil.sendWarningMessage(event.getPlayer(), new LocalizedChatMessage(ChatConstant.ERROR_REPAIR_OBJECTIVE)); event.setCancelled(true); } else { complete--; ObjectiveTouchEvent touchEvent = new ObjectiveTouchEvent(this, null, false); Bukkit.getServer().getPluginManager().callEvent(touchEvent); } } } } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onPistonPush(BlockPistonExtendEvent event) { for (Block block : event.getBlocks()) { if (monument.contains(block) && partOfObjective(block)) { event.setCancelled(true); } } } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onPistonRetract(BlockPistonRetractEvent event) { for (Block block : event.getBlocks()) { if (monument.contains(block) && partOfObjective(block)) { event.setCancelled(true); } } } public int getBlocksRequired() { return (int) Math.ceil(size * completion); } public int getBlocksBroken() { return (int) complete; } @EventHandler public void onPlayerDeath(PlayerDeathEvent event) { while (playersTouched.contains(event.getEntity().getUniqueId())) { playersTouched.remove(event.getEntity().getUniqueId()); } } public boolean showPercent() { return showPercent; } public boolean showProximity(TeamModule team) { return GameHandler.getGameHandler().getMatch().getModules().getModule(TimeLimit.class).getTimeLimit() != 0 && GameHandler.getGameHandler().getMatch().getModules().getModule(TimeLimit.class).getResult().equals(TimeLimit.Result.MOST_OBJECTIVES) && (team.isObserver() && proximityHandlers.size() == 1) || (!team.isObserver() && !team.equals(this.team)); } public boolean isRepairable() { return repairable; } public int getPercent() { double blocksRequired = completion * size; if (Math.floor((complete / blocksRequired) * 100) > 100) { return 100; } if (Math.floor((complete / blocksRequired) * 100) < 0) { return 0; } return (int) Math.floor((complete / blocksRequired) * 100); } public int getPercentFromAmount(int amount) { double blocksRequired = completion * size; if (Math.floor((amount / blocksRequired) * 100) > 100) { return 100; } if (Math.floor((amount / blocksRequired) * 100) < 0) { return 0; } return (int) Math.floor((amount / blocksRequired) * 100); } public boolean partOfObjective(Block block) { for (Pair<Material, Integer> material : materials) { if (material.getLeft().equals(block.getType()) && (material.getRight() == -1 || material.getRight() == (int) block.getState().getData().getData())) { return true; } } return false; } public List<Block> getBlocks() { List<Block> blocks = new ArrayList<>(); for (Block block : monument) { if (partOfObjective(block)) { blocks.add(block); } } return blocks; } public List<Block> getMonument() { return monument; } public String getWhoDestroyed(String locale) { String whoDestroyed = ""; List<String> toCombine = new ArrayList<>(); for (UUID player : MiscUtil.getSortedHashMapKeyset(playersCompleted)) { if (getPercentFromAmount(playersCompleted.get(player)) > (100 / 3)) { toCombine.add(Teams.getTeamColorByPlayer(Bukkit.getPlayer(player)) + Bukkit.getPlayer(player).getName() + ChatColor.WHITE + " (" + ChatColor.AQUA + getPercentFromAmount(playersCompleted.get(player)) + ChatColor.WHITE + "%)"); } } if (toCombine.size() == 0) { toCombine.add(new LocalizedChatMessage(ChatConstant.MISC_ENEMY).getMessage(locale)); } if (toCombine.size() < playersCompleted.keySet().size()) { toCombine.add(new LocalizedChatMessage(ChatConstant.MISC_OTHERS).getMessage(locale)); } whoDestroyed = toCombine.get(0); for (int i = 1; i < toCombine.size(); i++) { whoDestroyed += ChatColor.WHITE + (i == toCombine.size() - 1 ? " " + new LocalizedChatMessage(ChatConstant.MISC_AND).getMessage(locale) + " " : ", ") + toCombine.get(i); } return whoDestroyed; } public boolean changesModes() { return changesModes; } public void setMaterial(Material material, int damageValue) { materials.clear(); materials.add(new ImmutablePair<>(material, damageValue)); } @EventHandler public void onMonumentDestroy(ObjectiveCompleteEvent event) { if (event.getObjective().equals(this) && showOnScoreboard()) { Fireworks.spawnFireworks(region.getCenterBlock().getAlignedVector(), (region.getMax().minus(region.getMin()).length()) * 0.55 + 1, 6, MiscUtil.convertChatColorToColor(team.getColor()), 1); for (UUID player : playersCompleted.keySet()) { if (Bukkit.getOfflinePlayer(player).isOnline()) { Bukkit.getServer().getPluginManager().callEvent(new SnowflakeChangeEvent(Bukkit.getPlayer(player), Snowflakes.ChangeReason.MONUMENT_DESTROY, getPercentFromAmount(playersCompleted.get(player)) / 10, ChatColor.GREEN + "" + getPercentFromAmount(playersCompleted.get(player)) + ChatColor.GRAY, ChatColor.GREEN + name + ChatColor.GRAY)); } } } } public Double getProximity(TeamModule team) { return team.isObserver() ? (proximityHandlers.size() == 1 ? proximityHandlers.values().iterator().next().getProximity() : null) : (team.equals(this.team) ? null : proximityHandlers.get(team.getId()).getProximity()); } }