Skip to content

Commit

Permalink
Siege Improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
drfiveminusmint committed Feb 27, 2024
1 parent 6687b8c commit d596029
Show file tree
Hide file tree
Showing 8 changed files with 195 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ public class Config {
// Siege
public static boolean SiegeEnable;
public static int SiegeTaskSeconds = 600;
public static boolean SiegeNoRetreat;
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ public enum Stage {
@NotNull private final AtomicReference<Stage> stage;
@Nullable private LocalDateTime startTime;
@Nullable private OfflinePlayer player;
private boolean control;
private boolean suddenDeathActive;

public Siege(@NotNull Pair<String, SiegeConfig> nameAndConfig) {
name = nameAndConfig.getLeft();
Expand All @@ -35,6 +37,8 @@ public Siege(@NotNull Pair<String, SiegeConfig> nameAndConfig) {
stage.set(Stage.INACTIVE);
startTime = null;
player = null;
control = true;
suddenDeathActive = false;
}

@NotNull
Expand Down Expand Up @@ -66,6 +70,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(),
Expand All @@ -88,6 +100,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);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class SiegeConfig {
@NotNull private final String captureRegion;
@NotNull private final List<Integer> daysOfWeek;
@NotNull private final List<String> craftsToWin, commandsOnStart, commandsOnWin, commandsOnLose;
private final int scheduleStart, scheduleEnd, delayBeforeStart, duration, dailyIncome, cost;
private final int scheduleStart, scheduleEnd, delayBeforeStart, duration, suddenDeathDuration, dailyIncome, cost;
private final boolean doubleCostPerOwnedSiegeRegion;

public static Pair<String, SiegeConfig> load(Map.Entry<String, Map<String, ?>> config) {
Expand All @@ -32,6 +32,7 @@ public static Pair<String, SiegeConfig> load(Map.Entry<String, Map<String, ?>> c
(int) siegeMap.get("SiegeDuration"),
(int) siegeMap.get("DailyIncome"),
(int) siegeMap.get("CostToSiege"),
(int) siegeMap.getOrDefault("SuddenDeathDuration", 0),
(boolean) siegeMap.get("DoubleCostPerOwnedSiegeRegion")
));
}
Expand All @@ -41,7 +42,7 @@ private SiegeConfig(
@NotNull List<Integer> daysOfWeek,
@NotNull List<String> craftsToWin, @NotNull List<String> commandsOnStart,
@NotNull List<String> commandsOnWin, @NotNull List<String> commandsOnLose,
int scheduleStart, int scheduleEnd, int delayBeforeStart, int duration, int dailyIncome, int cost,
int scheduleStart, int scheduleEnd, int delayBeforeStart, int duration, int dailyIncome, int cost, int suddenDeathDuration,
boolean doubleCostPerOwnedSiegeRegion) {
this.attackRegion = attackRegion;
this.captureRegion = captureRegion;
Expand All @@ -56,6 +57,7 @@ private SiegeConfig(
this.duration = duration;
this.dailyIncome = dailyIncome;
this.cost = cost;
this.suddenDeathDuration = suddenDeathDuration;
this.doubleCostPerOwnedSiegeRegion = doubleCostPerOwnedSiegeRegion;
}

Expand Down Expand Up @@ -117,6 +119,8 @@ public int getCost() {
return cost;
}

public int getSuddenDeathDuration() {return suddenDeathDuration;}

public boolean isDoubleCostPerOwnedSiegeRegion() {
return doubleCostPerOwnedSiegeRegion;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
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.NORMAL)
public void onCraftMovement(CraftPreTranslateEvent event) {
Craft leaderCraft = event.getCraft();
if (!(leaderCraft instanceof PlayerCraft && Config.SiegeEnable && !event.isCancelled())) 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
public void onCraftRotation(CraftRotateEvent event) {
Craft leaderCraft = event.getCraft();
if (!(leaderCraft instanceof PlayerCraft && Config.SiegeEnable && !event.isCancelled())) 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
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()) {
Bukkit.getServer().broadcastMessage(String.format(I18nSupport.getInternationalisedString("Siege - Lost Control"),
player.getDisplayName(), currentSiege.getName()));
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()) {
Bukkit.getServer().broadcastMessage(String.format(I18nSupport.getInternationalisedString("Siege - Gained Control"),
player.getDisplayName(), currentSiege.getName(), leaderCraft.getType().getStringProperty(CraftType.NAME), leaderCraft.getOrigBlockCount(), leaderCraft.getHitBox().getMidPoint().toString()));
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.CANCEL);
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;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,18 @@ 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()) {
Bukkit.getServer().broadcastMessage(String.format(I18nSupport.getInternationalisedString("Siege - Sudden Death"),
siege.getName(), (timeLeft+2)/60));
if (!siege.leaderIsInControl()) {
endSiege();
} else {
siege.setSuddenDeathActive(true);
}
}

if (timeLeft % Config.SiegeTaskSeconds != 0)
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
12 changes: 8 additions & 4 deletions src/main/resources/localisation/mcwlang_en.properties
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ 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\ -\ 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.
Expand All @@ -53,6 +53,10 @@ 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\ 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
Expand Down

0 comments on commit d596029

Please sign in to comment.