Skip to content

Commit

Permalink
Add delay option for events
Browse files Browse the repository at this point in the history
Allows for delaying events when they initially start, so multiple events with the same "interval" can be scheduled in a more scattered fashion.
  • Loading branch information
Redned235 committed Dec 9, 2024
1 parent 1793151 commit 2180f54
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 37 deletions.
9 changes: 6 additions & 3 deletions plugin/src/main/java/org/battleplugins/arena/BattleArena.java
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,10 @@ public void onEnable() {

// Cheeky little message about BattleTracker <3
if (Bukkit.getPluginManager().getPlugin("BattleTracker") == null) {
this.warn("BattleTracker not found! Arena statistics will not be tracked. You can download BattleTracker at: https://modrinth.com/project/battletracker.");
this.warn("----------------------------------------");
this.warn("BattleTracker not found! Arena statistics will not be saved.");
this.warn("You can download BattleTracker at: https://modrinth.com/project/battletracker.");
this.warn("----------------------------------------");
}
}

Expand Down Expand Up @@ -237,8 +240,8 @@ void postInitialize() {
continue; // We are not interested in starting manual events
}

this.eventScheduler.scheduleEvent(arena, options);
this.info("Scheduled event for arena {} in {}m.", arena.getName(), options.getInterval());
this.eventScheduler.scheduleEvent(arena, options, true);
this.info("Scheduled event for arena {} in {}m.", arena.getName(), options.getInterval().plus(options.getDelay()));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.JoinConfiguration;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.Style;
import org.battleplugins.arena.Arena;
import org.battleplugins.arena.BattleArena;
import org.battleplugins.arena.competition.CompetitionType;
Expand Down Expand Up @@ -31,66 +33,78 @@ public BACommandExecutor(String parentCommand) {
}

@ArenaCommand(commands = "backups", description = "Shows backups that a player has saved.", permissionNode = "backups")
public void backups(Player player, @Argument(name = "player") String playerName) {
CompletableFuture.supplyAsync(() -> player.getServer().getOfflinePlayer(playerName)).thenAcceptAsync(target -> {
public void backups(CommandSender sender, @Argument(name = "player") String playerName) {
CompletableFuture.supplyAsync(() -> Bukkit.getServer().getOfflinePlayer(playerName)).thenAcceptAsync(target -> {
if (target == null) {
Messages.PLAYER_NOT_ONLINE.send(player, playerName);
Messages.PLAYER_NOT_ONLINE.send(sender, playerName);
return;
}

// Show backups
List<InventoryBackup> backups = InventoryBackup.load(target.getUniqueId());
if (backups.isEmpty()) {
Messages.NO_BACKUPS.send(player, target.getName());
Messages.NO_BACKUPS.send(sender, target.getName());
return;
}

Messages.HEADER.sendCentered(player, Messages.INVENTORY_BACKUPS);
Messages.HEADER.sendCentered(sender, Messages.INVENTORY_BACKUPS);

List<OptionSelector.Option> options = backups.stream().map(backup -> new OptionSelector.Option(
Messages.BACKUP_INFO.withContext(backup.getFormattedDate()),
"/ba restore " + target.getName() + " " + (backups.indexOf(backup) + 1)
)).toList();
OptionSelector.sendOptions(player, options, ClickEvent.Action.SUGGEST_COMMAND);
if (sender instanceof Player player) {
OptionSelector.sendOptions(player, options, ClickEvent.Action.SUGGEST_COMMAND);
} else {
for (int i = 0; i < options.size(); i++) {
// Console cannot click messages, so send command instead
OptionSelector.Option option = options.get(i);
Component message = Component.text("[" + (i + 1) + "] ", Messages.SECONDARY_COLOR)
.append(option.message().toComponent().style(Style.style(Messages.PRIMARY_COLOR)))
.append(Component.text(" (Run: \"" + option.command() + "\" to restore)", NamedTextColor.WHITE));

sender.sendMessage(message);
}
}
}, Bukkit.getScheduler().getMainThreadExecutor(BattleArena.getInstance()));
}

@ArenaCommand(commands = "restore", description = "Restores a backup for a player.", permissionNode = "restore")
public void restore(Player player, Player target, int backupIndex) {
public void restore(CommandSender sender, Player target, int backupIndex) {
backupIndex--;

// Restore backup
List<InventoryBackup> backups = InventoryBackup.load(target.getUniqueId());
if (backupIndex < 0 || backupIndex >= backups.size()) {
Messages.BACKUP_NOT_FOUND.send(player);
Messages.BACKUP_NOT_FOUND.send(sender);
return;
}

InventoryBackup backup = backups.get(backupIndex);
if (backup == null) {
Messages.BACKUP_NOT_FOUND.send(player);
Messages.BACKUP_NOT_FOUND.send(sender);
return;
}

backup.restore(target);
Messages.BACKUP_RESTORED.send(player, target.getName());
Messages.BACKUP_RESTORED.send(sender, target.getName());
}

@ArenaCommand(commands = "backup", description = "Creates a manual backup of a player's inventory.", permissionNode = "backup")
public void backup(Player player, Player target) {
public void backup(CommandSender sender, Player target) {
InventoryBackup.save(new InventoryBackup(target.getUniqueId(), target.getInventory().getContents()));
Messages.BACKUP_CREATED.send(player, target.getName());
Messages.BACKUP_CREATED.send(sender, target.getName());
}

@ArenaCommand(commands = "modules", description = "Lists all modules.", permissionNode = "modules")
public void modules(Player player) {
Messages.HEADER.sendCentered(player, Messages.MODULES);
public void modules(CommandSender sender) {
Messages.HEADER.sendCentered(sender, Messages.MODULES);

// All enabled modules
BattleArena.getInstance().getModules()
.stream()
.sorted(Comparator.comparing(module -> module.module().name()))
.forEach(module -> Messages.MODULE.send(player, Messages.wrap(module.module().name()), Messages.ENABLED));
.forEach(module -> Messages.MODULE.send(sender, Messages.wrap(module.module().name()), Messages.ENABLED));

// All failed modules
BattleArena.getInstance().getFailedModules()
Expand All @@ -110,76 +124,78 @@ public void modules(Player player) {
}

component = component.hoverEvent(Component.join(JoinConfiguration.newlines(), hoverLines));
player.sendMessage(component);
sender.sendMessage(component);
});
}

@ArenaCommand(commands = "start", description = "Starts an event manually.", permissionNode = "start")
public void event(Player player, Arena arena) {
public void event(CommandSender sender, Arena arena) {
if (arena.getType() != CompetitionType.EVENT) {
Messages.NOT_EVENT.send(player);
Messages.NOT_EVENT.send(sender);
return;
}

arena.getPlugin().getEventScheduler().startEvent(arena, new EventOptions(
EventType.MANUAL,
Duration.ZERO,
Duration.ZERO,
Messages.MANUAL_EVENT_MESSAGE.toComponent(arena.getName(), arena.getName().toLowerCase(Locale.ROOT))
));
}

@ArenaCommand(commands = "stop", description = "Stops an event manually.", permissionNode = "stop")
public void stop(Player player, Arena arena) {
public void stop(CommandSender sender, Arena arena) {
if (arena.getType() != CompetitionType.EVENT) {
Messages.NOT_EVENT.send(player);
Messages.NOT_EVENT.send(sender);
return;
}

arena.getPlugin().getEventScheduler().stopEvent(arena);
}

@ArenaCommand(commands = "stopall", description = "Stops all events manually.", permissionNode = "stopall")
public void stopAll(Player player) {
public void stopAll(CommandSender sender) {
for (Arena scheduledEvent : BattleArena.getInstance().getEventScheduler().getScheduledEvents()) {
BattleArena.getInstance().getEventScheduler().stopEvent(scheduledEvent);
}
}

@ArenaCommand(commands = "schedule", description = "Schedules an event to start at the specified time.", permissionNode = "schedule")
public void schedule(Player player, Arena arena, Duration interval) {
public void schedule(CommandSender sender, Arena arena, Duration interval) {
if (arena.getType() != CompetitionType.EVENT) {
Messages.NOT_EVENT.send(player);
Messages.NOT_EVENT.send(sender);
return;
}

arena.getPlugin().getEventScheduler().scheduleEvent(arena, new EventOptions(
EventType.SCHEDULED,
interval,
Duration.ZERO,
Messages.MANUAL_EVENT_MESSAGE.toComponent(arena.getName(), arena.getName().toLowerCase(Locale.ROOT))
));
), false);
}

@ArenaCommand(commands = "debug", description = "Toggles debug mode.", permissionNode = "debug")
public void debug(Player player) {
public void debug(CommandSender sender) {
BattleArena.getInstance().setDebugMode(!BattleArena.getInstance().isDebugMode());
Messages.DEBUG_MODE_SET_TO.send(player, Boolean.toString(BattleArena.getInstance().isDebugMode()));
Messages.DEBUG_MODE_SET_TO.send(sender, Boolean.toString(BattleArena.getInstance().isDebugMode()));
}

@ArenaCommand(commands = "reload", description = "Reloads the plugin.", permissionNode = "reload")
public void reload(Player player) {
Messages.STARTING_RELOAD.send(player);
public void reload(CommandSender sender) {
Messages.STARTING_RELOAD.send(sender);
long start = System.currentTimeMillis();

try {
BattleArena.getInstance().reload();
} catch (Exception e) {
Messages.RELOAD_FAILED.send(player);
Messages.RELOAD_FAILED.send(sender);
BattleArena.getInstance().error("Failed to reload plugin", e);
return;
}

long end = System.currentTimeMillis();
Messages.RELOAD_COMPLETE.send(player, Util.toUnitString(end - start, TimeUnit.MILLISECONDS));
Messages.RELOAD_COMPLETE.send(sender, Util.toUnitString(end - start, TimeUnit.MILLISECONDS));
}

public void sendHeader(CommandSender sender) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ public class EventOptions {
private EventType type;
@ArenaOption(name = "interval", required = true, description = "The interval of the event.")
private Duration interval;
@ArenaOption(name = "delay", description = "The delay until the event starts.")
private Duration delay = Duration.ZERO;
@ArenaOption(name = "message", required = true, description = "The message of the event.")
private Component message;

public EventOptions() {
}

public EventOptions(EventType type, Duration interval, Component message) {
public EventOptions(EventType type, Duration interval, Duration delay, Component message) {
this.type = type;
this.interval = interval;
this.message = message;
Expand All @@ -33,6 +35,10 @@ public Duration getInterval() {
return this.interval;
}

public Duration getDelay() {
return this.delay;
}

public Component getMessage() {
return this.message;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,22 @@ public class EventScheduler {
* @param arena the arena to schedule the event in
* @param options the options for the event
*/
public void scheduleEvent(Arena arena, EventOptions options) {
public void scheduleEvent(Arena arena, EventOptions options, boolean initial) {
ScheduledEvent scheduledEvent = this.scheduledEvents.get(arena);
if (scheduledEvent != null) {
scheduledEvent.task().cancel();

arena.getPlugin().info("An event is already scheduled in arena {}, cancelling the previous event.", arena.getName());
}

long timeTilStart = options.getInterval().toMillis() / 50;
if (initial) {
timeTilStart = options.getDelay().toMillis() / 50;
}

BukkitTask bukkitTask = Bukkit.getScheduler().runTaskLater(arena.getPlugin(), () -> {
this.startEvent(arena, options);
}, options.getInterval().toMillis() / 50);
}, timeTilStart);

this.scheduledEvents.put(arena, new ScheduledEvent(options, bukkitTask));
}
Expand Down Expand Up @@ -126,7 +131,7 @@ public void eventEnded(Arena arena, Competition<?> competition) {
return;
}

this.scheduleEvent(arena, scheduledEvent.options());
this.scheduleEvent(arena, scheduledEvent.options(), false);
arena.getPlugin().info("Event in arena {} has ended. Rescheduling event at interval.", arena.getName());
}

Expand Down
1 change: 1 addition & 0 deletions plugin/src/main/resources/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ events:
FFA:
- type: scheduled # Type of event
interval: 30m # Interval until start
delay: 5m # Delay until start
message: "<gold>[</gold><yellow>BattleArena</yellow><gold>]</gold> <yellow>A Free for All event is starting! Run <gold>/ffa join</gold> to join!</yellow>"

0 comments on commit 2180f54

Please sign in to comment.