package in.twizmwaz.cardinal.module.modules.ctf; import com.google.common.collect.EvictingQueue; import in.twizmwaz.cardinal.GameHandler; import in.twizmwaz.cardinal.chat.ChatConstant; import in.twizmwaz.cardinal.chat.LocalizedChatMessage; import in.twizmwaz.cardinal.event.MatchEndEvent; import in.twizmwaz.cardinal.event.PlayerChangeTeamEvent; import in.twizmwaz.cardinal.event.flag.FlagCaptureEvent; import in.twizmwaz.cardinal.event.flag.FlagDropEvent; import in.twizmwaz.cardinal.event.flag.FlagPickupEvent; import in.twizmwaz.cardinal.event.flag.FlagRespawnEvent; import in.twizmwaz.cardinal.module.GameObjective; import in.twizmwaz.cardinal.module.TaskedModule; import in.twizmwaz.cardinal.module.modules.ctf.net.Net; import in.twizmwaz.cardinal.module.modules.ctf.post.Post; import in.twizmwaz.cardinal.module.modules.filter.FilterModule; import in.twizmwaz.cardinal.module.modules.filter.FilterState; import in.twizmwaz.cardinal.module.modules.kit.KitNode; import in.twizmwaz.cardinal.module.modules.observers.ObserverModule; import in.twizmwaz.cardinal.module.modules.proximity.GameObjectiveProximityHandler; import in.twizmwaz.cardinal.module.modules.regions.RegionModule; import in.twizmwaz.cardinal.module.modules.regions.type.PointRegion; import in.twizmwaz.cardinal.module.modules.score.ScoreModule; import in.twizmwaz.cardinal.module.modules.scoreboard.GameObjectiveScoreboardHandler; import in.twizmwaz.cardinal.module.modules.scoreboard.ScoreboardModule; import in.twizmwaz.cardinal.module.modules.team.TeamModule; import in.twizmwaz.cardinal.module.modules.timeLimit.TimeLimit; import in.twizmwaz.cardinal.util.ArmorType; import in.twizmwaz.cardinal.util.ChatUtil; import in.twizmwaz.cardinal.util.Fireworks; import in.twizmwaz.cardinal.util.Flags; import in.twizmwaz.cardinal.util.MiscUtil; import in.twizmwaz.cardinal.util.PacketUtils; import in.twizmwaz.cardinal.util.Players; import in.twizmwaz.cardinal.util.Teams; import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.chat.TextComponent; import net.minecraft.server.EnumParticle; import net.minecraft.server.PacketPlayOutWorldParticles; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.DyeColor; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Sound; import org.bukkit.block.Banner; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.entity.ArmorStand; import org.bukkit.entity.Entity; 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.entity.ItemSpawnEvent; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.BannerMeta; import org.bukkit.material.MaterialData; import org.bukkit.util.Vector; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Queue; import java.util.Set; public class FlagObjective implements TaskedModule, GameObjective { private String id; private boolean show; private boolean required; private String name; private DyeColor color; private ChatColor chatColor; private Post post; // required private TeamModule owner; private boolean shared; // Default: false private String carryMessage; private int points; // Default: 0 private int pointsRate; // Default: 0 private FilterModule pickupFilter; private FilterModule dropFilter; private FilterModule captureFilter; private KitNode pickupKit; private KitNode dropKit; private KitNode carryKit; private boolean dropOnWater; private boolean beam; private FlagState state; private Banner banner; private ItemStack bannerItem; private Player picker; private Block currentFlagBlock; private Queue<Block> validPositions = EvictingQueue.create(5); private ItemStack pickerHelmet; private double respawnTime = 0; private double recoverTime = 0; private ArmorStand armorStand; private Long lastUpdate = 0L; private Long lastParticle = 0L; private Net lastNet = null; private FilterModule respawnFilter = null; private String respawnMessage = null; private GameObjectiveScoreboardHandler scoreboardHandler; private Map<String, GameObjectiveProximityHandler> flagProximityHandlers; private Map<String, GameObjectiveProximityHandler> netProximityHandlers; private boolean touched; private boolean complete; private boolean canRespawn; public FlagObjective(String id, boolean required, String name, DyeColor color, ChatColor chatColor, boolean show, Post post, TeamModule owner, boolean shared, String carryMessage, int points, int pointsRate, FilterModule pickupFilter, FilterModule dropFilter, FilterModule captureFilter, KitNode pickupKit, KitNode dropKit, KitNode carryKit, boolean dropOnWater, boolean beam, Set<Net> nets, Map<String, GameObjectiveProximityHandler> flagProximityHandlers, Map<String, GameObjectiveProximityHandler> netProximityHandlers) { this.id = id; this.required = required; this.name = name; this.color = color; this.chatColor = chatColor; this.show = show; this.post = post; this.owner = owner; this.shared = shared; if (shared) this.required = false; this.carryMessage = carryMessage; this.points = points; this.pointsRate = pointsRate; this.pickupFilter = pickupFilter; this.dropFilter = dropFilter; this.captureFilter = captureFilter; this.pickupKit = pickupKit; this.dropKit = dropKit; this.carryKit = carryKit; this.dropOnWater = dropOnWater; this.beam = beam; for (RegionModule region : post.getRegions()) { if (region.getCenterBlock().getBlock().getState() instanceof Banner) { this.banner = (Banner) region.getCenterBlock().getBlock().getState(); } } bannerItem = new ItemStack(Material.BANNER); BannerMeta meta = (BannerMeta) Bukkit.getItemFactory().getItemMeta(Material.BANNER); meta.setBaseColor(banner.getBaseColor()); meta.setPatterns(banner.getPatterns()); bannerItem.setItemMeta(meta); this.flagProximityHandlers = flagProximityHandlers; for (GameObjectiveProximityHandler proximityHandler : flagProximityHandlers.values()) { proximityHandler.setObjective(this); } this.netProximityHandlers = netProximityHandlers; for (GameObjectiveProximityHandler proximityHandler : netProximityHandlers.values()) { proximityHandler.setObjective(this); } currentFlagBlock = getPost().getInitialBlock(); state = FlagState.POST; scoreboardHandler = new GameObjectiveScoreboardHandler(this); for (Net net : nets) { net.setFlag(this); } for (Entity entity : GameHandler.getGameHandler().getMatchWorld().getEntities()) { if (entity instanceof ArmorStand && entity.getName().equals(getDisplayName()) && entity.getLocation().position().distance(getCurrentFlagLocation().position().plus(0,0.6875,0)) < 0.1) { entity.remove(); } } updateArmorStand(); if (this.owner == null) { int i = 0; for (TeamModule team : Teams.getTeams()) { if (!team.isObserver() && !pickupFilter.evaluate(team).equals(FilterState.ALLOW)) { this.owner = team; i++; } } if (i != 1) this.owner = null; } this.canRespawn = true; } @Override public void unload() { HandlerList.unregisterAll(this); } @Override public TeamModule getTeam() { return owner; } @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 boolean isRequired() { return required; } @Override public GameObjectiveScoreboardHandler getScoreboardHandler() { return scoreboardHandler; } @Override public GameObjectiveProximityHandler getProximityHandler(TeamModule team) { return isTouched() ? netProximityHandlers.get(team.getId()) : flagProximityHandlers.get(team.getId()); } public String getDisplayName() { return chatColor + getName(); } public ChatColor getChatColor() { return chatColor; } public Post getPost() { return post; } public Player getPicker() { return picker; } public boolean isPicker(Entity player) { return getPicker() != null && player.equals(getPicker()); } public void setPicker(Player picker) { this.picker = picker; } public boolean isOnPost() { return state.equals(FlagState.POST); } public boolean isCarried() { return state.equals(FlagState.CARRIED); } public boolean isDropped() { return state.equals(FlagState.DROPPED) || state.equals(FlagState.DROPPED_ON_WATER); } public boolean isWaitingToRespawn() { return state.equals(FlagState.WAITING_TO_RESPAWN); } public boolean isRespawning() { return state.equals(FlagState.RESPAWNING); } public int getPoints() { return points; } public int getRespawnTime() { return (int)(respawnTime + 0.99D); } public int getRecoverTime() { return (int)(recoverTime + 0.99); } public boolean isShared() { return shared; } public boolean multipleAttackers() { return flagProximityHandlers.size() > 1; } public Block getCurrentFlagBlock() { return currentFlagBlock; } public Location getCurrentFlagLocation() { return currentFlagBlock.getLocation().add(0.5,0,0.5); } public FilterModule getPickupFilter() { return pickupFilter; } public FilterModule getCaptureFilter() { return captureFilter; } public void setCanRespawn(boolean state) { this.canRespawn = state; setLastUpdate(); tickAndUpdate(); } public void setLastNet(Net net) { this.lastNet = net; } public void setRespawnFilter(FilterModule filter) { this.respawnFilter = filter; } public void setRespawnMessage(String respawnMessage) { this.respawnMessage = respawnMessage; } public Double getProximity(TeamModule team) { if (team.isObserver()) return flagProximityHandlers.size() == 1 ? (isTouched() ? netProximityHandlers.values().iterator().next().getProximity() : flagProximityHandlers.values().iterator().next().getProximity()) : null; if (team.equals(this.owner)) return null; return isTouched() ? netProximityHandlers.get(team.getId()).getProximity() : flagProximityHandlers.get(team.getId()).getProximity(); } public boolean showProximity(TeamModule team) { return GameHandler.getGameHandler().getMatch().getModules().getModule(TimeLimit.class).getTimeLimit() != 0 && ((team.isObserver() && flagProximityHandlers.size() == 1) || flagProximityHandlers.containsKey(team.getId())); } private Block nextSpawn() { RegionModule spawn = getPost().getNextFlagSpawn(); Block block; if (spawn instanceof PointRegion) { block = ((PointRegion) spawn).getBlock(); } else { block = spawn.getRandomPoint().getBlock(); } return block; } public void respawnFlag() { if (GameHandler.getGameHandler().getMatch().isRunning()) { state = FlagState.POST; FlagRespawnEvent e = new FlagRespawnEvent(this, getPost(), currentFlagBlock); this.complete = false; this.respawnFilter = null; this.respawnMessage = null; Bukkit.getServer().getPluginManager().callEvent(e); for (Player p : Bukkit.getOnlinePlayers()) { p.sendMessage(new LocalizedChatMessage(ChatConstant.UI_FLAG_RESPAWNED, getDisplayName() + ChatColor.RESET).getMessage(p.getLocale())); } spawnFlag(); } } private void resetValidPositions(Block block) { validPositions.clear(); if (block != null) validPositions.add(block); } private void setLastValidBlock() { currentFlagBlock = null; List<Block> blocks = new ArrayList<>(validPositions); Collections.reverse(blocks); for (Block block : blocks) { if (validatePosition(block)) { currentFlagBlock = block; break; } } } private void spawnFlag() { if (!isOnPost()) { setLastValidBlock(); if (currentFlagBlock == null) { armorStand.remove(); currentFlagBlock = nextSpawn(); state = FlagState.WAITING_TO_RESPAWN; respawnTime = getPost().getRespawnTime(picker.getLocation(), currentFlagBlock.getLocation()); resetPlayer(); updateFlags(); return; } } currentFlagBlock.setType(banner.getMaterial()); currentFlagBlock = currentFlagBlock.getLocation().getBlock(); Banner newBanner = (Banner)currentFlagBlock.getState(); newBanner.setPatterns(banner.getPatterns()); newBanner.setBaseColor(banner.getBaseColor()); armorStand = createArmorStand(); if (!isOnPost()) { if (currentFlagBlock.getRelative(BlockFace.DOWN).getType().equals(Material.STATIONARY_WATER)) { currentFlagBlock.getRelative(BlockFace.DOWN).setType(Material.ICE); state = FlagState.DROPPED_ON_WATER; } else { state = FlagState.DROPPED; } Flags.setBannerFacing(Flags.yawToFace(picker.getLocation().getYaw()), newBanner); FlagDropEvent event = new FlagDropEvent(getPicker(), this); Bukkit.getPluginManager().callEvent(event); } else { Flags.setBannerFacing(getPost().getYaw(), newBanner); } Player oldPicker = picker; this.lastNet = null; resetPlayer(); for (Player player : Bukkit.getOnlinePlayers()) { if (oldPicker != null && player.equals(oldPicker)) continue; getPost().tryPickupFlag(player, player.getLocation(), null, this); if (picker != null) break; } } private ArmorStand createArmorStand() { Location loc = getCurrentFlagLocation().add(0,0.6875,0); ArmorStand armorStand = GameHandler.getGameHandler().getMatchWorld().spawn(loc, ArmorStand.class); armorStand.setGravity(false); armorStand.setVisible(false); armorStand.setSmall(true); armorStand.setBasePlate(false); armorStand.setCustomNameVisible(true); armorStand.setCustomName(getDisplayName()); return armorStand; } private void updateArmorStand() { if (armorStand == null || armorStand.isDead()) armorStand = createArmorStand(); String suffix = isDropped() && GameHandler.getGameHandler().getMatch().isRunning() ? ChatColor.AQUA + " " + getRecoverTime() : ""; armorStand.setCustomName(getDisplayName() + suffix); } private boolean validatePosition(Block block) { return ((block.getRelative(BlockFace.DOWN).getType().isSolid() || (dropOnWater && block.getRelative(BlockFace.DOWN).getType().equals(Material.STATIONARY_WATER))) && block.isEmpty() && block.getRelative(BlockFace.UP).isEmpty()); } public void sendActionBar(boolean set) { if (picker == null) return; if (set) picker.sendMessage(ChatMessageType.ACTION_BAR, new TextComponent(carryMessage)); else picker.sendMessage(ChatMessageType.ACTION_BAR, new TextComponent("")); } private void resetPlayer() { if (picker != null) { sendActionBar(false); picker.hideTitle(); picker.getInventory().setHelmet(pickerHelmet); if (dropKit != null) dropKit.apply(picker, null); if (carryKit != null) carryKit.remove(picker); pickerHelmet = null; picker = null; } } private void updateScoreboard() { if (isDropped() || isOnPost()) updateArmorStand(); for (ScoreboardModule scoreboard : GameHandler.getGameHandler().getMatch().getModules().getModules(ScoreboardModule.class)) { scoreboard.updateObjectivePrefix(this); } } private void sendParticles() { Location loc = picker != null ? picker.getLocation() : getCurrentFlagLocation(); Long time = System.currentTimeMillis(); if ((isOnPost() || isDropped()) && lastParticle < time - 500) { lastParticle = time; PacketPlayOutWorldParticles portalPacket = new PacketPlayOutWorldParticles(EnumParticle.PORTAL, false, (float)loc.getX(), (float)loc.getY() + 1f, (float)loc.getZ(), 0f, 0f, 0f, 1f, 8); PacketUtils.broadcastPacket(portalPacket); } if (beam) { loc.add(0, 56.0, 0); PacketPlayOutWorldParticles packet = new PacketPlayOutWorldParticles(EnumParticle.ITEM_CRACK, true, (float)loc.getX(), (float)loc.getY(), (float)loc.getZ(), 0.15f, 24.0f, 0.15f, 0.0f, 40, 35, (int)color.getWoolData()); PacketUtils.broadcastPacket(packet); } } public boolean inRange(Location newLoc, Location oldLoc) { Location flag = getCurrentFlagLocation().clone(); double dx = Math.abs(newLoc.getX() - flag.getX()); double dy = Math.abs(newLoc.getY() - (flag.getY() - 0.5)); double dz = Math.abs(newLoc.getZ() - flag.getZ()); if (dx < 1D && dz < 1D && dy < 2.5D) { Vector flagY0 = flag.toVector().clone(); flagY0.setY(0); Vector newY0 = newLoc.toVector().clone(); newY0.setY(0); double dist1 = flagY0.distance(newY0); if (dist1 < 1D) { if (oldLoc == null) return true; Location oldY0 = oldLoc.clone(); oldY0.setY(0); double dist2 = flagY0.distance(oldY0.position()); return dist1 < dist2; } } return false; } @EventHandler public void onPlayerPickupFlag(FlagPickupEvent event) { if (!event.getFlag().equals(this)) return; Fireworks.spawnFlagFirework(getCurrentFlagLocation(), MiscUtil.convertChatColorToColor(chatColor)); Players.playSoundEffect(event.getPlayer(), Sound.ENTITY_FIREWORK_BLAST, 1, 1f); Players.playSoundEffect(event.getPlayer(), Sound.ENTITY_FIREWORK_TWINKLE, 1, 1f); TeamModule pickerTeam = Teams.getTeamByPlayer(event.getPlayer()).orNull(); for (TeamModule team : Teams.getTeams()) { if (team.isObserver() || team == pickerTeam) { Players.broadcastSoundEffect(team, Sound.ENTITY_FIREWORK_BLAST, 1, 0.7f); } else { Players.broadcastSoundEffect(team, Sound.ENTITY_WITHER_AMBIENT, 0.7f, 1.2f); } } this.touched = true; if (pickupKit != null) pickupKit.apply(event.getPlayer(), null); if (carryKit != null) carryKit.apply(event.getPlayer(), null); pickerHelmet = event.getPlayer().getInventory().getHelmet(); event.getPlayer().getInventory().setHelmet(bannerItem); currentFlagBlock.setType(Material.AIR); if (state.equals(FlagState.DROPPED_ON_WATER)) currentFlagBlock.getRelative(BlockFace.DOWN).setType(Material.STATIONARY_WATER); for (Player p : Bukkit.getOnlinePlayers()) { p.sendMessage(new LocalizedChatMessage(ChatConstant.UI_FLAG_PICKED_UP, getDisplayName() + ChatColor.RESET, Teams.getTeamByPlayer(event.getPlayer()).get().getColor() + event.getPlayer().getName()).getMessage(p.getLocale())); } setPicker(event.getPlayer()); state = FlagState.CARRIED; armorStand.remove(); sendActionBar(true); event.getPlayer().showTitle(new TextComponent(""), new TextComponent(carryMessage), 0, 20, 10); resetValidPositions(currentFlagBlock); } @EventHandler public void onDropFlag(FlagDropEvent event) { if (!event.getFlag().equals(this)) return; Fireworks.spawnFlagFirework(getCurrentFlagLocation(), MiscUtil.convertChatColorToColor(chatColor)); TeamModule pickerTeam = Teams.getTeamByPlayer(event.getPlayer()).orNull(); for (TeamModule team : Teams.getTeams()) { if (team.isObserver() || team == pickerTeam) { Players.broadcastSoundEffect(team, Sound.ENTITY_FIREWORK_TWINKLE_FAR, 1, 1f); } else { Players.broadcastSoundEffect(team, Sound.ENTITY_WITHER_HURT, 0.7f, 1f); } } for (Player p : Bukkit.getOnlinePlayers()) { p.sendMessage(new LocalizedChatMessage(ChatConstant.UI_FLAG_DROPPED, getDisplayName() + ChatColor.RESET).getMessage(p.getLocale())); } recoverTime = getPost().getRecoverTime(); setLastUpdate(); tickAndUpdate(); } @EventHandler public void onFlagRespawn(FlagRespawnEvent event) { if (!event.getFlag().equals(this)) return; Fireworks.spawnFlagFirework(getCurrentFlagLocation(), MiscUtil.convertChatColorToColor(chatColor)); for (TeamModule team : Teams.getTeams()) { if (team.isObserver() || team != owner) { Players.broadcastSoundEffect(team, Sound.ENTITY_FIREWORK_TWINKLE_FAR, 1f, 1f); } else { Players.broadcastSoundEffect(team, Sound.ENTITY_ZOMBIE_VILLAGER_CONVERTED, 1, 1.2f); } } } @EventHandler public void onCaptureFlag(FlagCaptureEvent event) { if (!event.getFlag().equals(this)) return; if (event.getNet().getPost() != null) post = event.getNet().getPost(); state = canRespawn ? FlagState.RESPAWNING : FlagState.WAITING_TO_RESPAWN; this.complete = true; this.touched = false; this.lastNet = null; currentFlagBlock = nextSpawn(); respawnTime = getPost().getRespawnTime(event.getPlayer().getLocation(), currentFlagBlock.getLocation()); resetPlayer(); setLastUpdate(); tickAndUpdate(); } @EventHandler public void onMove(PlayerMoveEvent event) { if (ObserverModule.testObserverOrDead(event.getPlayer())) return; Player player = event.getPlayer(); if (!event.getFrom().getBlock().equals(event.getTo().getBlock()) && picker != null && player.equals(picker)) { if (validatePosition(event.getTo().getBlock())) { validPositions.add(event.getTo().getBlock()); } else if (event.getTo().getBlock().getType().equals(Material.STATIONARY_WATER) && validatePosition(event.getTo().getBlock().getRelative(BlockFace.UP))) { validPositions.add(event.getTo().getBlock().getRelative(BlockFace.UP)); } } if (!event.getFrom().getBlock().equals(currentFlagBlock)) getPost().tryPickupFlag(player, event.getTo(), event.getFrom(), this); } @EventHandler public void onBlockBreak(BlockBreakEvent event) { if (isOnPost() || isDropped()) { if (event.getBlock().equals(currentFlagBlock)) { event.setCancelled(true); event.getPlayer().sendMessage(ChatColor.RED + new LocalizedChatMessage(ChatConstant.ERROR_BREAK_FLAG).getMessage(event.getPlayer().getLocale())); } else if (event.getBlock().getRelative(BlockFace.UP).equals(currentFlagBlock)) { event.setCancelled(true); event.getPlayer().sendMessage(ChatColor.RED + new LocalizedChatMessage(ChatConstant.ERROR_BREAK_BLOCK_UNDER_FLAG).getMessage(event.getPlayer().getLocale())); } } } @EventHandler public void onDead(PlayerDeathEvent event) { if (isPicker(event.getEntity())) { spawnFlag(); } } @EventHandler public void onTeamChange(PlayerChangeTeamEvent event) { if (isPicker(event.getPlayer())) { spawnFlag(); } } @EventHandler public void onLeave(PlayerQuitEvent event) { if (isPicker(event.getPlayer())) { spawnFlag(); } } @EventHandler public void onInventoryClick(InventoryClickEvent event) { if (isPicker(event.getWhoClicked()) && event.getSlot() == ArmorType.HELMET.getSlot()) { event.setCancelled(true); event.setCurrentItem(null); spawnFlag(); } } @EventHandler public void onItemDrop(PlayerDropItemEvent event) { if (isPicker(event.getPlayer()) && event.getItemDrop().getItemStack().isSimilar(bannerItem)) { event.getItemDrop().remove(); spawnFlag(); } } @EventHandler public void onItemSpawn(ItemSpawnEvent event) { if (event.getEntity().getItemStack().equals(bannerItem)) { event.getEntity().remove(); } } @EventHandler(priority = EventPriority.LOW) public void onMatchEnd(MatchEndEvent event) { if (isCarried()) { spawnFlag(); } tickAndUpdate(); } @Override public void run() { sendParticles(); if (GameHandler.getGameHandler().getMatch().isRunning()) { if (System.currentTimeMillis() - lastUpdate > 100) { tickAndUpdate(); } } } private void tickAndUpdate() { updateFlags(); updateScoreboard(); } private void setLastUpdate() { lastUpdate = System.currentTimeMillis(); } private void updateFlags() { double diff = (double)(System.currentTimeMillis() - lastUpdate) / 1000; setLastUpdate(); if (isOnPost() && getPost().getPointsRate() != 0 && post.getOwner() != null) { addPoints(post.getOwner() , (double)getPost().getPointsRate() * diff); } if (isCarried() && pointsRate != 0) { addPoints(owner != null ? owner : Teams.getTeamByPlayer(picker).get(), (double) pointsRate * diff); } if (isCarried() && lastNet != null) { lastNet.tryCapture(this); } if (isDropped()) { if (recoverTime > 0) { double max = Math.min(recoverTime, diff); recoverTime -= max; diff -= max; } if (recoverTime == 0) { Fireworks.spawnFlagFirework(getCurrentFlagLocation(), MiscUtil.convertChatColorToColor(chatColor)); currentFlagBlock.setType(Material.AIR); if (state.equals(FlagState.DROPPED_ON_WATER)) currentFlagBlock.getRelative(BlockFace.DOWN).setType(Material.STATIONARY_WATER); Location oldBlock = currentFlagBlock.getLocation(); armorStand.remove(); currentFlagBlock = nextSpawn(); state = FlagState.WAITING_TO_RESPAWN; respawnTime = getPost().getRespawnTime(oldBlock, currentFlagBlock.getLocation()); } } if (isWaitingToRespawn() && canRespawn) { state = FlagState.RESPAWNING; } if (isRespawning()) { if (respawnTime > 0) { double max = Math.min(respawnTime, diff); respawnTime -= max; } if (respawnTime == 0) { if ((respawnFilter == null || !respawnFilter.evaluate().equals(FilterState.DENY))) { respawnFlag(); } else if (respawnMessage != null) { ChatUtil.getGlobalChannel().sendMessage(respawnMessage); respawnMessage = null; } } } sendActionBar(true); } private void addPoints(TeamModule team, double points) { for (ScoreModule score : GameHandler.getGameHandler().getMatch().getModules().getModules(ScoreModule.class)) { if (team.equals(score.getTeam())) { score.addScore(points); } } } public enum FlagState { POST, CARRIED, DROPPED, DROPPED_ON_WATER, WAITING_TO_RESPAWN, RESPAWNING; } }