Skip to content

Commit

Permalink
Merge pull request #5 from das-kaesebrot/feature/ingame-commands
Browse files Browse the repository at this point in the history
Merge in-game commands into main
  • Loading branch information
das-kaesebrot authored Mar 9, 2023
2 parents b0464c2 + c327510 commit 91ea0d4
Show file tree
Hide file tree
Showing 8 changed files with 252 additions and 49 deletions.
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,5 @@ test {
shadowJar {
relocate 'com.cronutils', 'eu.kaesebrot.dev.dependencies.cronutils'
}
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
29 changes: 20 additions & 9 deletions src/main/java/eu/kaesebrot/dev/CronAnnouncerPlugin.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
package eu.kaesebrot.dev;

import eu.kaesebrot.dev.classes.CronAnnouncerConfiguration;
import eu.kaesebrot.dev.classes.ScheduledMessage;
import eu.kaesebrot.dev.commands.CronAnnouncerCommand;
import eu.kaesebrot.dev.tasks.ScheduledMessageTaskScheduler;
import eu.kaesebrot.dev.utils.ScheduleConfigParser;
import eu.kaesebrot.dev.utils.TickConverter;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitTask;

import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.Map;

public class CronAnnouncerPlugin extends JavaPlugin {
private ScheduleConfigParser scheduleConfigParser;
private final TickConverter tickConverter = new TickConverter();
Expand All @@ -21,12 +17,12 @@ public class CronAnnouncerPlugin extends JavaPlugin {
@Override
public void onEnable() {
this.saveDefaultConfig();

scheduleConfigParser = new ScheduleConfigParser(this);
configuration = scheduleConfigParser.parseConfig();

cancelAllTasks();
queueInitialScheduler();
// Register our command "kit" (set an instance of your command class as executor)
this.getCommand("cronannouncer").setExecutor(new CronAnnouncerCommand(this));

init(); // innit mate
}

@Override
Expand All @@ -35,6 +31,21 @@ public void onDisable() {
getLogger().info(getName() + " has been disabled!");
}

public void init() {
reloadCronAnnouncerConfig();
cancelAllTasks();
queueInitialScheduler();
}

public CronAnnouncerConfiguration getCronAnnouncerConfig() {
return this.configuration;
}

public void reloadCronAnnouncerConfig() {
this.reloadConfig();
configuration = scheduleConfigParser.parseConfig();
}

private void queueInitialScheduler() {
if (configuration.getScheduledMessageMap().isEmpty()) {
getLogger().info("Skipping adding the initial scheduler, no scheduled messages given");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
import java.util.Map;

public class CronAnnouncerConfiguration {
private Map<String, ScheduledMessage> scheduledMessageMap;
private Duration queueAheadDuration;
private Duration pollingInterval;
private final Map<String, ScheduledMessage> scheduledMessageMap;
private final Duration queueAheadDuration;
private final Duration pollingInterval;

public CronAnnouncerConfiguration(Map<String, ScheduledMessage> scheduledMessageMap, Duration queueAheadDuration, Duration pollingInterval) {
this.scheduledMessageMap = scheduledMessageMap;
Expand Down
28 changes: 6 additions & 22 deletions src/main/java/eu/kaesebrot/dev/classes/ScheduledMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,21 @@

import java.util.Map;

public class ScheduledMessage {
private final MessageType type;
private final String text;
private final Cron schedule;

public ScheduledMessage(String text, Cron schedule, MessageType type) {
this.text = text;
this.schedule = schedule;
this.type = type;
}

public String getText() {
return text;
}

public Cron getSchedule() {
return schedule;
}
public MessageType getType() {
return type;
}
public record ScheduledMessage(String text, Cron schedule, MessageType type) {

@Override
public String toString() {
return String.format("ScheduledMessage(message='%s', schedule='%s', type='%s')", this.text, this.schedule.asString(), this.type.toString().toLowerCase());
}

public String toStringInCommand() {
return String.format(" message: %s\u00A7r\n schedule: %s\n type: %s\n", this.text, this.schedule.asString(), this.type.toString().toLowerCase());
}

public Map<String, String> asStringMap() {
return Map.of(
"message", this.text,
"schedule", this.getSchedule().asString(),
"schedule", this.schedule().asString(),
"type", type.toString().toLowerCase());
}
}
172 changes: 172 additions & 0 deletions src/main/java/eu/kaesebrot/dev/commands/CronAnnouncerCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
package eu.kaesebrot.dev.commands;

import eu.kaesebrot.dev.CronAnnouncerPlugin;
import eu.kaesebrot.dev.utils.ScheduleConfigParser;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class CronAnnouncerCommand implements CommandExecutor {
private final String KEY_ROOT = "schedules"; // keep this key in sync with ScheduleConfigParser!
private final String SUBCOMMAND_LIST = "list";
private final String SUBCOMMAND_ADD = "add";
private final String SUBCOMMAND_REMOVE = "rm";
private final String SUBCOMMAND_RELOAD = "reload";

private final String PERMISSION_SEPARATOR = ".";
private final String PERMISSION_ROOT = "eu.kaesebrot.dev.cronannouncer";
private final String PERMISSION_LIST = PERMISSION_ROOT + PERMISSION_SEPARATOR + "list";
private final String PERMISSION_ADD = PERMISSION_ROOT + PERMISSION_SEPARATOR + "add";
private final String PERMISSION_REMOVE = PERMISSION_ROOT + PERMISSION_SEPARATOR + "remove";
private final String PERMISSION_RELOAD = PERMISSION_ROOT + PERMISSION_SEPARATOR + "reload";
private final CronAnnouncerPlugin plugin;

public CronAnnouncerCommand(CronAnnouncerPlugin plugin) {
this.plugin = plugin;
}

@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
// don't handle if the args are empty or if the command doesn't come from a player
if (!(sender instanceof Player player) || args.length == 0)
return false;

List<String> argsList = Arrays.asList(args);

switch (argsList.get(0)) {
case SUBCOMMAND_LIST -> {
if (args.length == 1 && player.hasPermission(PERMISSION_LIST)) {
player.sendMessage(listRegisteredMessages());
return true;
}
}
case SUBCOMMAND_ADD -> {
// command: /cronannouncer add name "schedule" "message" type
argsList = correctlyParseArgsWithQuotes(argsList);

if (argsList.size() == 5 && player.hasPermission(PERMISSION_ADD)) {
String key = argsList.get(1).replaceAll("^\"|\"$", "");
String schedule = argsList.get(2);
String message = argsList.get(3);
String type = argsList.get(4);

if (plugin.getCronAnnouncerConfig().getScheduledMessageMap().containsKey(key)) {
player.sendMessage(String.format("Key '%s' already exists, please pick another name", key));
return false;
}

try {
var newMessage = new ScheduleConfigParser(plugin).parseFromStrings(schedule, message, type);

plugin.getLogger().info(String.format("Added new message via command: %s", newMessage.toString()));

plugin.getConfig().set(String.format("%s.%s", KEY_ROOT, key), newMessage.asStringMap());
plugin.saveConfig();
plugin.init();

player.sendMessage(String.format("Successfully added new message:\n[%s]\n%s\n", key, newMessage.toStringInCommand()));

return true;

} catch (Exception e) {
player.sendMessage("Error while parsing!\nSyntax: /cronannouncer add <unique-name> \"<cron-expression>\" \"<message-text>\" <type>");
return false;
}
}
}
case SUBCOMMAND_REMOVE -> {
if (args.length == 2 && player.hasPermission(PERMISSION_REMOVE)) {
var messageKey = argsList.get(1).toLowerCase();
if (removeScheduledMessage(messageKey)) {
player.sendMessage(String.format("Successfully removed scheduled message '%s'", messageKey));
return true;
} else {
player.sendMessage(String.format("Failed removing scheduled message - no message found by key '%s'", messageKey));
return false;
}
}
}
case SUBCOMMAND_RELOAD -> {
if (args.length == 1 && player.hasPermission(PERMISSION_RELOAD)) {
plugin.init();
player.sendMessage("Reload successful");
return true;
}
}
}

return false;
}

private String listRegisteredMessages()
{
var messages = plugin.getCronAnnouncerConfig().getScheduledMessageMap();

if (messages.isEmpty())
return "No scheduled messages registered (yet!)";

StringBuilder returnText = new StringBuilder();
returnText.append("Registered messages:\n");

for (var message : messages.entrySet()) {
returnText.append(String.format("[%s]\n%s\n", message.getKey(), message.getValue().toStringInCommand()));
}

return returnText.toString();
}

private boolean removeScheduledMessage(String messageKey)
{
var messages = plugin.getCronAnnouncerConfig().getScheduledMessageMap();

if (messages.containsKey(messageKey)) {
plugin.getConfig().set(String.format("%s.%s", KEY_ROOT, messageKey), null);
plugin.saveConfig();
plugin.init();
return true;
}

return false;
}

private List<String> correctlyParseArgsWithQuotes(List<String> args) {

List<String> parsedArgs = new ArrayList<>();
String argsString = String.join(" ", args).trim() + " "; // add a space to the end to cover the last element

boolean quoteFound = false;
int lastQuoteIndex = 0;
int lastSpaceIndex = -1;

for (int index = 0; index < argsString.length(); index++) {
if (argsString.charAt(index) == '\"') {
if (quoteFound) {
parsedArgs.add(argsString.substring(lastQuoteIndex + 1, index));
} else {
lastQuoteIndex = index;
}

quoteFound = !quoteFound;
}

if (!quoteFound
&& argsString.charAt(index) == ' '
&& argsString.charAt(index - 1) != '\"') {
parsedArgs.add(argsString.substring(lastSpaceIndex + 1, index));
}

if (argsString.charAt(index) == ' ') {
lastSpaceIndex = index;
}
}

plugin.getLogger().info(parsedArgs.toString());

return parsedArgs;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public void run()
for (var scheduledMessage: scheduledMessages.entrySet()) {
var message = scheduledMessage.getValue();

var nextRunTicksForMessage = tickConverter.getNextRunTicksUntil(scheduledMessage.getValue().getSchedule(),
var nextRunTicksForMessage = tickConverter.getNextRunTicksUntil(scheduledMessage.getValue().schedule(),
searchDateStart, searchDateEnd);

if (nextRunTicksForMessage.isEmpty())
Expand Down Expand Up @@ -145,9 +145,9 @@ private void updateReference() {
}

private BukkitRunnable getRunnableForMessage(ScheduledMessage message) {
return switch (message.getType()) {
case TITLE -> new TitleTask(plugin, message.getText());
case BROADCAST -> new BroadcastTask(plugin, message.getText());
return switch (message.type()) {
case TITLE -> new TitleTask(plugin, message.text());
case BROADCAST -> new BroadcastTask(plugin, message.text());
default -> throw new IllegalArgumentException("Illegal message type provided");
};
}
Expand Down
31 changes: 20 additions & 11 deletions src/main/java/eu/kaesebrot/dev/utils/ScheduleConfigParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@

public class ScheduleConfigParser
{
private String KEY_ROOT = "schedules";
private String KEY_MESSAGE = "message";
private String KEY_SCHEDULE = "schedule";
private final String KEY_ROOT = "schedules";
private final String KEY_MESSAGE = "message";
private final String KEY_SCHEDULE = "schedule";

private String KEY_QUEUE_DURATION = "queue_duration";
private String KEY_POLLING_INTERVAL = "polling_interval";
private String KEY_TYPE = "type";
private final String KEY_QUEUE_DURATION = "queue_duration";
private final String KEY_POLLING_INTERVAL = "polling_interval";
private final String KEY_TYPE = "type";
private final CronParser parser;

private final JavaPlugin plugin;
Expand Down Expand Up @@ -74,6 +74,16 @@ private Map<String, ScheduledMessage> parseMessages()
return parsedMessages;
}

public ScheduledMessage parseFromStrings(String schedule, String messageText, String type) {
var parsedCronValue = parser.parse(schedule.replaceAll("^\"|\"$", ""));
var parsedText = messageText
.replaceAll("(&([a-f0-9]))", "\u00A7$2")
.replaceAll("^\"|\"$", "");
var parsedType = MessageType.valueOf(type.replaceAll("^\"|\"$", "").toUpperCase());

return new ScheduledMessage(parsedText, parsedCronValue, parsedType);
}

private ScheduledMessage parseEntry(MemorySection scheduleEntry) {
if (!(
scheduleEntry.contains(KEY_MESSAGE)
Expand All @@ -83,10 +93,9 @@ private ScheduledMessage parseEntry(MemorySection scheduleEntry) {
throw new IllegalArgumentException("Invalid schedule entry");
}

var parsedCronValue = parser.parse(scheduleEntry.getString(KEY_SCHEDULE));
var parsedText = scheduleEntry.getString(KEY_MESSAGE).replaceAll("(&([a-f0-9]))", "\u00A7$2");
var parsedType = MessageType.valueOf(scheduleEntry.getString(KEY_TYPE).toUpperCase());

return new ScheduledMessage(parsedText, parsedCronValue, parsedType);
return parseFromStrings(
scheduleEntry.getString(KEY_SCHEDULE),
scheduleEntry.getString(KEY_MESSAGE),
scheduleEntry.getString(KEY_TYPE));
}
}
25 changes: 25 additions & 0 deletions src/main/resources/plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,28 @@ name: CronAnnouncer
version: 1.0.0
main: eu.kaesebrot.dev.CronAnnouncerPlugin
api-version: 1.19

commands:
cronannouncer:
description: Your description
usage: "Usage: /<command> [list | add | rm <message-key> | reload]"
permission: eu.kaesebrot.dev.cronannouncer
aliases: cron

permissions:
eu.kaesebrot.dev.cronannouncer.*:
description: Gives access to all CronAnnouncer commands
children:
eu.kaesebrot.dev.cronannouncer.list: true
eu.kaesebrot.dev.cronannouncer.add: true
eu.kaesebrot.dev.cronannouncer.remove: true
eu.kaesebrot.dev.cronannouncer.reload: true

eu.kaesebrot.dev.cronannouncer.list:
description: Listing of scheduled messages
eu.kaesebrot.dev.cronannouncer.add:
description: Adding new scheduled messages
eu.kaesebrot.dev.cronannouncer.remove:
description: Removing scheduled messages
eu.kaesebrot.dev.cronannouncer.reload:
description: Reload CronAnnouncer config file

0 comments on commit 91ea0d4

Please sign in to comment.