diff --git a/src/main/java/net/countercraft/movecraft/warfare/MovecraftWarfare.java b/src/main/java/net/countercraft/movecraft/warfare/MovecraftWarfare.java index c598b4d..9018caa 100644 --- a/src/main/java/net/countercraft/movecraft/warfare/MovecraftWarfare.java +++ b/src/main/java/net/countercraft/movecraft/warfare/MovecraftWarfare.java @@ -10,6 +10,7 @@ import net.countercraft.movecraft.warfare.features.assault.commands.AssaultRepairCommand; import net.countercraft.movecraft.warfare.features.assault.listener.AssaultExplosionListener; import net.countercraft.movecraft.warfare.features.siege.SiegeCommand; +import net.countercraft.movecraft.warfare.features.siege.SiegeLeaderListener; import net.countercraft.movecraft.warfare.features.siege.SiegeManager; import net.countercraft.movecraft.warfare.localisation.I18nSupport; import net.countercraft.movecraft.worldguard.MovecraftWorldGuard; @@ -94,9 +95,11 @@ public void onEnable() { if (Config.SiegeEnable) { Config.SiegeTaskSeconds = getConfig().getInt("SiegeTaskSeconds", 600); + Config.SiegeNoRetreat = getConfig().getBoolean("SiegeNoRetreat", true); getLogger().info("Enabling siege"); siegeManager = new SiegeManager(this); siegeManager.runTaskTimerAsynchronously(this, 0, 20); + getServer().getPluginManager().registerEvents(new SiegeLeaderListener(), this); } getCommand("siege").setExecutor(new SiegeCommand()); diff --git a/src/main/java/net/countercraft/movecraft/warfare/config/Config.java b/src/main/java/net/countercraft/movecraft/warfare/config/Config.java index 7135956..a93b333 100644 --- a/src/main/java/net/countercraft/movecraft/warfare/config/Config.java +++ b/src/main/java/net/countercraft/movecraft/warfare/config/Config.java @@ -30,4 +30,5 @@ public class Config { // Siege public static boolean SiegeEnable; public static int SiegeTaskSeconds = 600; + public static boolean SiegeNoRetreat; } diff --git a/src/main/java/net/countercraft/movecraft/warfare/features/siege/Siege.java b/src/main/java/net/countercraft/movecraft/warfare/features/siege/Siege.java index d31905c..b047360 100644 --- a/src/main/java/net/countercraft/movecraft/warfare/features/siege/Siege.java +++ b/src/main/java/net/countercraft/movecraft/warfare/features/siege/Siege.java @@ -25,6 +25,8 @@ public enum Stage { @NotNull private final AtomicReference stage; @Nullable private LocalDateTime startTime; @Nullable private OfflinePlayer player; + private boolean control; + private boolean suddenDeathActive; public Siege(@NotNull String siegeName, @NotNull SiegeConfig siegeConfig) { name = siegeName; @@ -33,6 +35,8 @@ public Siege(@NotNull String siegeName, @NotNull SiegeConfig siegeConfig) { stage.set(Stage.INACTIVE); startTime = null; player = null; + control = true; + suddenDeathActive = false; } @NotNull @@ -64,6 +68,14 @@ public String getName() { return name; } + public boolean leaderIsInControl() {return control;} + + public void setLeaderInControl(boolean b) {control = b;} + + public boolean isSuddenDeathActive() {return suddenDeathActive;} + + public void setSuddenDeathActive (boolean b) {suddenDeathActive = b;} + public void start(@NotNull Player player, long cost) { for (String startCommand : config.getCommandsOnStart()) { Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), @@ -86,6 +98,8 @@ public void start(@NotNull Player player, long cost) { MovecraftRepair.getInstance().getEconomy().withdrawPlayer(player, cost); startTime = LocalDateTime.now(); this.player = player; + this.suddenDeathActive = false; + this.control = true; setStage(Stage.PREPARATION); } diff --git a/src/main/java/net/countercraft/movecraft/warfare/features/siege/SiegeCommand.java b/src/main/java/net/countercraft/movecraft/warfare/features/siege/SiegeCommand.java index afb9391..f6d9cad 100644 --- a/src/main/java/net/countercraft/movecraft/warfare/features/siege/SiegeCommand.java +++ b/src/main/java/net/countercraft/movecraft/warfare/features/siege/SiegeCommand.java @@ -21,6 +21,8 @@ import org.jetbrains.annotations.Nullable; import java.text.NumberFormat; +import java.time.Duration; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; @@ -63,43 +65,42 @@ else if (args[0].equalsIgnoreCase("info")) else if (args[0].equalsIgnoreCase("time")) return timeCommand(commandSender); else if (args[0].equalsIgnoreCase("cancel")) - return cancelCommand(commandSender, args); + return cancelCommand(commandSender); + else if (args[0].equalsIgnoreCase("status")) + return statusCommand(commandSender); commandSender.sendMessage( MOVECRAFT_COMMAND_PREFIX + I18nSupport.getInternationalisedString("Siege - Invalid Argument")); return true; } - private boolean cancelCommand(CommandSender commandSender, String[] args) { + private boolean cancelCommand(CommandSender commandSender) { if (!commandSender.hasPermission("movecraft.siege.cancel")) { commandSender.sendMessage( MOVECRAFT_COMMAND_PREFIX + I18nSupport.getInternationalisedString("Insufficient Permissions")); return true; } - if (args.length <= 1) { - commandSender.sendMessage( - MOVECRAFT_COMMAND_PREFIX + I18nSupport.getInternationalisedString("Siege - Specify Region")); - return true; - } - - StringBuilder sb = new StringBuilder(); - for (int i = 1; i < args.length; i++) { - if (i > 1) - sb.append(" "); - sb.append(args[i]); - } - String region = sb.toString(); for (Siege siege : MovecraftWarfare.getInstance().getSiegeManager().getSieges()) { if (siege.getStage().get() == Siege.Stage.INACTIVE) continue; - if (!region.equalsIgnoreCase(siege.getName())) - continue; - - cancelSiege(siege); + if((commandSender instanceof Player)) { + if (siege.getPlayer().equals((Player) commandSender) || commandSender.hasPermission("movecraft.siege.cancel.other")) { + cancelSiege(siege); + } else { + commandSender.sendMessage(I18nSupport.getInternationalisedString("Insufficient Permissions")); + } + } else { + if (commandSender.hasPermission("movecraft.siege.cancel.other")) { + cancelSiege(siege); + } else { + commandSender.sendMessage(I18nSupport.getInternationalisedString("Insufficient Permissions")); + } + } return true; } + commandSender.sendMessage(I18nSupport.getInternationalisedString("Siege - No Siege Active")); return false; } @@ -127,6 +128,11 @@ private void cancelSiege(Siege siege) { } private boolean timeCommand(CommandSender commandSender) { + if (!commandSender.hasPermission("movecraft.siege.time")) { + commandSender.sendMessage(MOVECRAFT_COMMAND_PREFIX + I18nSupport.getInternationalisedString("Insufficient Permissions")); + return true; + } + int militaryTime = getMilitaryTime(); commandSender.sendMessage(MOVECRAFT_COMMAND_PREFIX + dayToString(getDayOfWeek()) + " - " + String.format("%02d", militaryTime / 100) + ":" + String.format("%02d", militaryTime % 100)); @@ -134,6 +140,11 @@ private boolean timeCommand(CommandSender commandSender) { } private boolean infoCommand(CommandSender commandSender, String[] args) { + if (!commandSender.hasPermission("movecraft.siege.info")) { + commandSender.sendMessage(MOVECRAFT_COMMAND_PREFIX + I18nSupport.getInternationalisedString("Insufficient Permissions")); + return true; + } + if (args.length <= 1) { commandSender.sendMessage( MOVECRAFT_COMMAND_PREFIX + I18nSupport.getInternationalisedString("Siege - Specify Region")); @@ -181,6 +192,8 @@ private boolean infoCommand(CommandSender commandSender, String[] args) { + militaryTimeIntToString(siege.getConfig().getScheduleEnd()) + " UTC"); commandSender.sendMessage(I18nSupport.getInternationalisedString("Siege - Duration") + ChatColor.WHITE + secondsIntToString(siege.getConfig().getDuration())); + commandSender.sendMessage(I18nSupport.getInternationalisedString("Siege - Sudden Death Duration") + ChatColor.WHITE + + secondsIntToString(siege.getConfig().getSuddenDeathDuration())); return true; } @@ -211,6 +224,11 @@ private String secondsIntToString(int seconds) { } private boolean listCommand(CommandSender commandSender, String[] args) { + if (!commandSender.hasPermission("movecraft.siege.list")) { + commandSender.sendMessage(MOVECRAFT_COMMAND_PREFIX + I18nSupport.getInternationalisedString("Insufficient Permissions")); + return true; + } + SiegeManager siegeManager = MovecraftWarfare.getInstance().getSiegeManager(); int page; try { @@ -245,6 +263,12 @@ private boolean beginCommand(CommandSender commandSender) { return true; } + if (!commandSender.hasPermission("movecraft.siege.begin")) { + commandSender.sendMessage(MOVECRAFT_COMMAND_PREFIX + + I18nSupport.getInternationalisedString("Insufficient Permissions")); + return true; + } + SiegeManager siegeManager = MovecraftWarfare.getInstance().getSiegeManager(); Player player = (Player) commandSender; for (Siege siege : siegeManager.getSieges()) { @@ -309,6 +333,63 @@ private boolean beginCommand(CommandSender commandSender) { return true; } + private Boolean statusCommand(CommandSender commandSender) { + if (!commandSender.hasPermission("movecraft.siege.status")) { + commandSender.sendMessage(MOVECRAFT_COMMAND_PREFIX + + I18nSupport.getInternationalisedString("Insufficient Permissions")); + return true; + } + + for (Siege siege : MovecraftWarfare.getInstance().getSiegeManager().getSieges()) { + if (siege.getStage().get() == Siege.Stage.INACTIVE) + continue; + + Duration timePassed = Duration.between(siege.getStartTime(), LocalDateTime.now()); + + StringBuilder message = new StringBuilder(); + if (siege.getStage().get() == Siege.Stage.PREPARATION) { + long timeLeft = siege.getConfig().getDelayBeforeStart() - timePassed.getSeconds(); + message.append(String.format(I18nSupport.getInternationalisedString("Siege - Siege About To Begin"), + siege.getPlayer().getName(), + siege.getName())); + message.append(SiegeUtils.formatMinutes(timeLeft)); + commandSender.sendMessage(message.toString()); + return true; + } + long timeLeft = siege.getConfig().getDuration() - timePassed.getSeconds(); + Craft siegeCraft = CraftManager.getInstance().getCraftByPlayer(siege.getPlayer().getPlayer()); + if (siege.leaderIsInControl()) { + message.append(String.format(I18nSupport.getInternationalisedString("Siege - Flagship In Box"), + siege.getName(), + siegeCraft.getType().getStringProperty(CraftType.NAME), + siegeCraft.getOrigBlockCount(), + siege.getPlayer().getName(), + siegeCraft.getHitBox().getMidPoint().getX(), + siegeCraft.getHitBox().getMidPoint().getY(), + siegeCraft.getHitBox().getMidPoint().getZ())); + message.append(SiegeUtils.formatMinutes(timeLeft)); + } else { + message.append(String.format(I18nSupport.getInternationalisedString("Siege - Flagship Not In Box"), + siege.getName(), + siegeCraft.getType().getStringProperty(CraftType.NAME), + siegeCraft.getOrigBlockCount(), + siege.getPlayer().getName(), + siegeCraft.getHitBox().getMidPoint().getX(), + siegeCraft.getHitBox().getMidPoint().getY(), + siegeCraft.getHitBox().getMidPoint().getZ())); + message.append(SiegeUtils.formatMinutes(timeLeft)); + } + commandSender.sendMessage(message.toString()); + if (siege.isSuddenDeathActive()) { + commandSender.sendMessage(String.format(I18nSupport.getInternationalisedString("Siege - Sudden Death"), siege.getPlayer().getName(), (timeLeft / 60) + 1)); + } + return true; + } + commandSender.sendMessage(MOVECRAFT_COMMAND_PREFIX + + I18nSupport.getInternationalisedString("Siege - No Siege Underway")); + return true; + } + @Nullable private Siege getSiege(@NotNull Player player, SiegeManager siegeManager) { Set regions = MovecraftWorldGuard.getInstance().getWGUtils().getRegions(player.getLocation()); @@ -383,20 +464,20 @@ private String dayToString(int day) { public List onTabComplete(CommandSender commandSender, Command command, String s, String[] strings) { final List tabCompletions = new ArrayList<>(); if (strings.length <= 1) { - tabCompletions.add("info"); - tabCompletions.add("begin"); - tabCompletions.add("list"); - tabCompletions.add("time"); - tabCompletions.add("cancel"); + if (commandSender.hasPermission("movecraft.siege.info")) + tabCompletions.add("info"); + if (commandSender.hasPermission("movecraft.siege.begin")) + tabCompletions.add("begin"); + if (commandSender.hasPermission("movecraft.siege.list")) + tabCompletions.add("list"); + if (commandSender.hasPermission("movecraft.siege.time")) + tabCompletions.add("time"); + if (commandSender.hasPermission("movecraft.siege.cancel")) + tabCompletions.add("cancel"); + if (commandSender.hasPermission("movecraft.siege.status")) + tabCompletions.add("status"); } else if (strings[0].equalsIgnoreCase("info")) { for (Siege siege : MovecraftWarfare.getInstance().getSiegeManager().getSieges()) { - tabCompletions.add(siege.getName()); - } - } else if (strings[0].equalsIgnoreCase("cancel")) { - for (Siege siege : MovecraftWarfare.getInstance().getSiegeManager().getSieges()) { - if (siege.getStage().get() == Siege.Stage.INACTIVE) - continue; - tabCompletions.add(siege.getName()); } } diff --git a/src/main/java/net/countercraft/movecraft/warfare/features/siege/SiegeConfig.java b/src/main/java/net/countercraft/movecraft/warfare/features/siege/SiegeConfig.java index 7ba93ef..00affb5 100644 --- a/src/main/java/net/countercraft/movecraft/warfare/features/siege/SiegeConfig.java +++ b/src/main/java/net/countercraft/movecraft/warfare/features/siege/SiegeConfig.java @@ -10,7 +10,7 @@ public class SiegeConfig { @NotNull private final String captureRegion; @NotNull private final List daysOfWeek; @NotNull private final List craftsToWin, commandsOnStart, commandsOnWin, commandsOnLose; - private final int scheduleStart, scheduleEnd, delayBeforeStart, duration, dailyIncome, cost; + private final int scheduleStart, scheduleEnd, delayBeforeStart, duration, dailyIncome, cost, suddenDeathDuration; private final boolean doubleCostPerOwnedSiegeRegion; public SiegeConfig(ConfigurationSection config) { @@ -61,6 +61,16 @@ public SiegeConfig(ConfigurationSection config) { if(!config.isBoolean("DoubleCostPerOwnedSiegeRegion")) throw new IllegalArgumentException("Invalid DoubleCostPerOwnedSiegeRegion"); doubleCostPerOwnedSiegeRegion = config.getBoolean("DoubleCostPerOwnedSiegeRegion"); + + // Since this is a new addition to the siege file and optional, + // get it if present but ignore it if not + if (config.contains("SiegeSuddenDeathDuration")) { + if(!config.isInt("SiegeSuddenDeathDuration")) + throw new IllegalArgumentException("Invalid SiegeSuddenDeathDuration"); + suddenDeathDuration = config.getInt("SiegeSuddenDeathDuration"); + } else { + suddenDeathDuration = 0; + } } @NotNull @@ -122,6 +132,10 @@ public int getCost() { return cost; } + public int getSuddenDeathDuration() { + return suddenDeathDuration; + } + public boolean isDoubleCostPerOwnedSiegeRegion() { return doubleCostPerOwnedSiegeRegion; } diff --git a/src/main/java/net/countercraft/movecraft/warfare/features/siege/SiegeLeaderListener.java b/src/main/java/net/countercraft/movecraft/warfare/features/siege/SiegeLeaderListener.java new file mode 100644 index 0000000..63461ad --- /dev/null +++ b/src/main/java/net/countercraft/movecraft/warfare/features/siege/SiegeLeaderListener.java @@ -0,0 +1,155 @@ +package net.countercraft.movecraft.warfare.features.siege; + +import net.countercraft.movecraft.MovecraftLocation; +import net.countercraft.movecraft.craft.Craft; +import net.countercraft.movecraft.craft.PlayerCraft; +import net.countercraft.movecraft.craft.type.CraftType; +import net.countercraft.movecraft.events.CraftPreTranslateEvent; +import net.countercraft.movecraft.events.CraftReleaseEvent; +import net.countercraft.movecraft.events.CraftRotateEvent; +import net.countercraft.movecraft.events.CraftSinkEvent; +import net.countercraft.movecraft.util.ChatUtils; +import net.countercraft.movecraft.warfare.MovecraftWarfare; +import net.countercraft.movecraft.warfare.config.Config; +import net.countercraft.movecraft.warfare.features.siege.events.SiegeBroadcastEvent; +import net.countercraft.movecraft.warfare.localisation.I18nSupport; +import net.countercraft.movecraft.worldguard.MovecraftWorldGuard; +import net.countercraft.movecraft.worldguard.utils.IsInRegion; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + + + +public class SiegeLeaderListener implements Listener { + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onCraftMovement(CraftPreTranslateEvent event) { + Craft leaderCraft = event.getCraft(); + if (!(leaderCraft instanceof PlayerCraft) || !Config.SiegeEnable) return; + Player player = ((PlayerCraft)leaderCraft).getPilot(); + Siege currentSiege = getSiegeByLeader(player); + if (currentSiege == null) return; + + // Get the minimum and maximum positions + MovecraftLocation newMinLocation = new MovecraftLocation( + leaderCraft.getHitBox().getMinX(), + leaderCraft.getHitBox().getMinY(), + leaderCraft.getHitBox().getMinZ() + ).translate(event.getDx(), event.getDy(),event.getDz()); + MovecraftLocation newMaxLocation = new MovecraftLocation( + leaderCraft.getHitBox().getMaxX(), + leaderCraft.getHitBox().getMaxY(), + leaderCraft.getHitBox().getMaxZ() + ).translate(event.getDx(),event.getDy(),event.getDz()); + + event.setCancelled(processCraftMovement(leaderCraft,player,currentSiege,newMaxLocation,newMinLocation)); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onCraftRotation(CraftRotateEvent event) { + Craft leaderCraft = event.getCraft(); + if (!(leaderCraft instanceof PlayerCraft) || !Config.SiegeEnable) return; + Player player = ((PlayerCraft)leaderCraft).getPilot(); + Siege currentSiege = getSiegeByLeader(player); + if (currentSiege == null) return; + MovecraftLocation newMinLocation = new MovecraftLocation( + event.getNewHitBox().getMinX(), + event.getNewHitBox().getMinY(), + event.getNewHitBox().getMinZ() + ); + MovecraftLocation newMaxLocation = new MovecraftLocation( + event.getNewHitBox().getMaxX(), + event.getNewHitBox().getMaxY(), + event.getNewHitBox().getMaxZ() + ); + event.setCancelled(processCraftMovement(leaderCraft,player,currentSiege,newMaxLocation,newMinLocation)); + } + @EventHandler + public void onCraftSink (CraftSinkEvent event) { + processCraftRemoval(event.getCraft()); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onCraftRelease (CraftReleaseEvent event) { + processCraftRemoval(event.getCraft()); + } + + private void processCraftRemoval(Craft leaderCraft) { + if (!(leaderCraft instanceof PlayerCraft) || !Config.SiegeEnable) return; + Player player = ((PlayerCraft)leaderCraft).getPilot(); + Siege currentSiege = getSiegeByLeader(player); + if (currentSiege == null) return; + if (currentSiege.leaderIsInControl()) { + String broadcast = String.format(I18nSupport.getInternationalisedString("Siege - Lost Control"), + player.getDisplayName(), currentSiege.getName()); + Bukkit.getServer().broadcastMessage(broadcast); + SiegeBroadcastEvent event = new SiegeBroadcastEvent(currentSiege, broadcast, SiegeBroadcastEvent.Type.LOSE_CONTROL); + Bukkit.getServer().getPluginManager().callEvent(event); + currentSiege.setLeaderInControl(false); + if (currentSiege.isSuddenDeathActive()) + endSiege(currentSiege); + } + } + + private boolean processCraftMovement(Craft leaderCraft, Player player, Siege currentSiege, MovecraftLocation newMaxLocation, MovecraftLocation newMinLocation) { + IsInRegion regionTester = MovecraftWorldGuard.getInstance().getWGUtils().getIsInRegion(currentSiege.getConfig().getAttackRegion(), leaderCraft.getWorld()); + if (regionTester == null) return false; + + // Check to see that both corners are in the siege box + if (!regionTester.test(newMaxLocation) || !regionTester.test(newMinLocation)) { + if (currentSiege.leaderIsInControl() && Config.SiegeNoRetreat) { + player.sendMessage(ChatUtils.MOVECRAFT_COMMAND_PREFIX + I18nSupport.getInternationalisedString("Siege - No Retreat")); + return true; + } + } else if (!currentSiege.leaderIsInControl()) { + String broadcast = String.format(I18nSupport.getInternationalisedString("Siege - Gained Control"), + player.getDisplayName(), currentSiege.getName(), leaderCraft.getType().getStringProperty(CraftType.NAME), leaderCraft.getOrigBlockCount(), leaderCraft.getHitBox().getMidPoint().toString()); + Bukkit.getServer().broadcastMessage(broadcast); + SiegeBroadcastEvent event = new SiegeBroadcastEvent(currentSiege, broadcast, SiegeBroadcastEvent.Type.GAIN_CONTROL); + Bukkit.getServer().getPluginManager().callEvent(event); + currentSiege.setLeaderInControl(true); + } + return false; + } + + private void endSiege(Siege siege) { + String playerName = SiegeUtils.getSiegeLeaderName(siege.getPlayer()); + + String broadcast = String.format(I18nSupport.getInternationalisedString("Siege - Siege Failure"), + siege.getName(), playerName); + Bukkit.getServer().broadcastMessage(broadcast); + + siege.setStage(Siege.Stage.INACTIVE); + + playerName = siege.getPlayer().getName(); + if (playerName == null) + playerName = "null"; + for (String command : siege.getConfig().getCommandsOnLose()) { + Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), command + .replaceAll("%r", siege.getConfig().getCaptureRegion()) + .replaceAll("%c", "" + siege.getConfig().getCost()) + .replaceAll("%l", playerName)); + } + + SiegeBroadcastEvent event = new SiegeBroadcastEvent(siege, broadcast, SiegeBroadcastEvent.Type.LOSE); + Bukkit.getServer().getPluginManager().callEvent(event); + } + + @Nullable + private Siege getSiegeByLeader (@NotNull Player leader) { + for (Siege s : MovecraftWarfare.getInstance().getSiegeManager().getSieges()) { + if (s.getStage().get().equals(Siege.Stage.INACTIVE)) continue; + if (s.getPlayer() == null) continue; + if (s.getPlayer().equals(leader)) { + return s; + } else { + return null; + } + } + return null; + } +} diff --git a/src/main/java/net/countercraft/movecraft/warfare/features/siege/events/SiegeBroadcastEvent.java b/src/main/java/net/countercraft/movecraft/warfare/features/siege/events/SiegeBroadcastEvent.java index 416e017..41cf698 100644 --- a/src/main/java/net/countercraft/movecraft/warfare/features/siege/events/SiegeBroadcastEvent.java +++ b/src/main/java/net/countercraft/movecraft/warfare/features/siege/events/SiegeBroadcastEvent.java @@ -16,7 +16,10 @@ public enum Type { PROGRESS_NOT_IN_BOX, WIN, LOSE, - CANCEL + CANCEL, + SUDDEN_DEATH, + GAIN_CONTROL, + LOSE_CONTROL } private static final HandlerList HANDLERS = new HandlerList(); private final String broadcast; diff --git a/src/main/java/net/countercraft/movecraft/warfare/features/siege/tasks/SiegeProgressTask.java b/src/main/java/net/countercraft/movecraft/warfare/features/siege/tasks/SiegeProgressTask.java index 9e37e0b..b037d8e 100644 --- a/src/main/java/net/countercraft/movecraft/warfare/features/siege/tasks/SiegeProgressTask.java +++ b/src/main/java/net/countercraft/movecraft/warfare/features/siege/tasks/SiegeProgressTask.java @@ -6,6 +6,7 @@ import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; +import org.bukkit.Sound; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -39,8 +40,24 @@ public void run() { // Siege is done! endSiege(); return; - } else { - // Siege is still in progress + } + // Siege is still in progress + + // Check if it's time to begin sudden death + if (!siege.isSuddenDeathActive() && timeLeft < siege.getConfig().getSuddenDeathDuration()) { + String broadcast = String.format(I18nSupport.getInternationalisedString("Siege - Sudden Death"), + siege.getName(), (timeLeft+2)/60); + Bukkit.getServer().broadcastMessage(broadcast); + SiegeBroadcastEvent event = new SiegeBroadcastEvent(siege, broadcast, SiegeBroadcastEvent.Type.SUDDEN_DEATH); + Bukkit.getServer().getPluginManager().callEvent(event); + if (!siege.leaderIsInControl()) { + endSiege(); + } else { + for (Player p : Bukkit.getOnlinePlayers()) { + p.playSound(p.getLocation(), Sound.ENTITY_WITHER_DEATH, 1, 0.25F); + } + siege.setSuddenDeathActive(true); + } } if (timeLeft % Config.SiegeTaskSeconds != 0) diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 79665ad..fa3de54 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -53,3 +53,4 @@ AssaultDestroyableBlocks: # these blocks will be removed if destroyed in assault SiegeEnable: true SiegeTaskSeconds: 600 # Seconds per siege message, defaults to 600 (10 minutes) +SiegeNoRetreat: true # Lock the siege leader inside the siege box diff --git a/src/main/resources/localisation/mcwlang_en.properties b/src/main/resources/localisation/mcwlang_en.properties index 71ebbe2..e083670 100644 --- a/src/main/resources/localisation/mcwlang_en.properties +++ b/src/main/resources/localisation/mcwlang_en.properties @@ -32,17 +32,19 @@ Siege\ -\ Day\ of\ Week=Day of week\: Siege\ -\ Start\ Time=Start time\: Siege\ -\ End\ Time=End time\: Siege\ -\ Duration=Duration\: -Siege\ -\ Flagship\ In\ Box=The Siege of %s is under way. The Siege Flagship is a %s of size %d under the command of %s at %d, %d, %d. Siege will end +Siege\ -\ Sudden\ Death\ Duration=Sudden Death Duration\: +Siege\ -\ Flagship\ In\ Box=The Siege of %s is under way. The Siege Flagship is a(n) %s of size %d under the command of %s at %d, %d, %d. Siege will end Siege\ -\ Flagship\ Not\ In\ Box=The Siege of %s is under way. The Siege Leader, %s, is not in command of a Flagship within the Siege Region\! If they are still not when the duration expires, the siege will fail\! Siege will end in Siege\ -\ Siege\ Success=The Siege of %s has succeeded\! The forces of %s have been victorious\! Siege\ -\ Siege\ Failure=The Siege of %s has failed\! The forces of %s have been crushed\! -Siege\ -\ Ending\ Soon=soon -Siege\ -\ Ending\ In\ 1\ Minute=in 1 minute -Siege\ -\ Ending\ In\ X\ Minutes=in %d minutes +Siege\ -\ Ending\ Soon=soon. +Siege\ -\ Ending\ In\ 1\ Minute=in 1 minute. +Siege\ -\ Ending\ In\ X\ Minutes=in %d minutes. Siege\ -\ Siege\ Not\ Configured=Siege is not configured on this server. Siege\ -\ No\ Argument=No argument specified, valid arguments include begin, info, and list. Siege\ -\ Invalid\ Argument=Invalid argument specified, valid arguments include begin, info, and list. Siege\ -\ Specify\ Region=You need to supply a siege region. +Siege\ -\ No\ Siege\ Underway=No siege is currently underway. Siege\ -\ Siege\ About\ To\ Begin=%s is preparing to siege %s\! All players wishing to participate in the defense should head there immediately\! Siege will begin Siege\ -\ Log\ Siege\ Start=Siege: %s commenced by %s for a cost of %d. Siege\ -\ Must\ Be\ Player=You need to be a player to siege. @@ -53,6 +55,11 @@ Siege\ -\ No\ Configuration\ Found=Could not find a siege configuration for the Siege\ -\ Siege\ Region\ Not\ Found=Siege region not found. Use '/siege list' to find valid siege regions. Siege\ -\ Default\ Siege\ Start\ Cancel\ Reason=Your siege was cancelled by a plugin. Event\ -\ Default\ Cancel\ Reason=Sorry, the performed action was cancelled by a plugin. +Siege\ -\ No\ Siege\ Active=No siege is currently underway. +Siege\ -\ No\ Retreat=You are the siege leader, and cannot retreat! Use '/siege cancel' to cancel the siege. +Siege\ -\ Gained\ Control=%s has gained control of the %s siege region! Their flagship is a(n) %s of size %d at %s. +Siege\ -\ Lost\ Control=%s has lost control of the %s siege region! +Siege\ -\ Sudden\ Death=The siege of %s has entered sudden death. The siege leader must survive the next %d minute(s) to win. Siege\ -\ Monday=Monday Siege\ -\ Tuesday=Tuesday Siege\ -\ Wednesday=Wednesday