Skip to content

Commit 36abeeb

Browse files
authored
GH-87 Complete project overhaul — Architecture, Performance, Scheduling, Messaging, Configuration
2 parents 5baa605 + 14e2a5c commit 36abeeb

File tree

119 files changed

+3909
-2745
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

119 files changed

+3909
-2745
lines changed

.github/workflows/gradle.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ jobs:
2121
runs-on: ubuntu-latest
2222
steps:
2323
- uses: actions/checkout@v3
24-
- name: Set up JDK 17
24+
- name: Set up JDK 21
2525
uses: actions/setup-java@v3
2626
with:
27-
java-version: '17'
27+
java-version: '21'
2828
distribution: 'temurin'
2929

3030
- name: Setup Gradle
@@ -37,4 +37,4 @@ jobs:
3737
run: ./gradlew build
3838

3939
- name: Build the Jar
40-
run: ./gradlew shadowJar
40+
run: ./gradlew shadowJar

automessage-core/build.gradle.kts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
dependencies {
2+
compileOnlyApi("org.spigotmc:spigot-api:1.21.10-R0.1-SNAPSHOT")
3+
4+
implementation("net.kyori:adventure-platform-bukkit:4.4.1")
5+
implementation("net.kyori:adventure-text-minimessage:4.21.0")
6+
7+
implementation("com.eternalcode:multification-bukkit:1.2.2")
8+
implementation("com.eternalcode:multification-okaeri:1.2.2")
9+
10+
api("eu.okaeri:okaeri-configs-yaml-snakeyaml:5.0.9")
11+
implementation("eu.okaeri:okaeri-configs-serdes-commons:5.0.5")
12+
13+
implementation("org.bstats:bstats-bukkit:3.1.0")
14+
implementation("dev.rollczi:litecommands-bukkit:3.10.6")
15+
implementation("dev.rollczi:litecommands-annotations:3.10.6")
16+
17+
testImplementation("org.junit.jupiter:junit-jupiter:6.0.1")
18+
testImplementation("org.assertj:assertj-core:3.25.2")
19+
testImplementation("org.mockito:mockito-core:5.8.0")
20+
testImplementation("org.mockito:mockito-junit-jupiter:5.8.0")
21+
testImplementation("org.mockito:mockito-inline:5.2.0")
22+
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
23+
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package com.github.imdmk.automessage;
2+
3+
import com.eternalcode.multification.notice.Notice;
4+
import com.github.imdmk.automessage.command.dispatcher.DisableCommand;
5+
import com.github.imdmk.automessage.command.dispatcher.EnableCommand;
6+
import com.github.imdmk.automessage.command.reload.ReloadCommand;
7+
import com.github.imdmk.automessage.config.ConfigManager;
8+
import com.github.imdmk.automessage.platform.litecommands.handler.InvalidUsageHandlerImpl;
9+
import com.github.imdmk.automessage.platform.litecommands.handler.MissingPermissionsHandlerImpl;
10+
import com.github.imdmk.automessage.platform.litecommands.handler.NoticeResultHandlerImpl;
11+
import com.github.imdmk.automessage.platform.logger.BukkitPluginLogger;
12+
import com.github.imdmk.automessage.platform.logger.PluginLogger;
13+
import com.github.imdmk.automessage.platform.scheduler.BukkitTaskScheduler;
14+
import com.github.imdmk.automessage.platform.scheduler.TaskScheduler;
15+
import com.github.imdmk.automessage.scheduled.ScheduledMessagesConfig;
16+
import com.github.imdmk.automessage.scheduled.audience.filter.AudienceFilter;
17+
import com.github.imdmk.automessage.scheduled.dispatcher.MessageDispatcher;
18+
import com.github.imdmk.automessage.scheduled.dispatcher.MessageDispatcherConfig;
19+
import com.github.imdmk.automessage.scheduled.dispatcher.MessageDispatcherTask;
20+
import com.github.imdmk.automessage.scheduled.selector.MessageSelector;
21+
import com.github.imdmk.automessage.scheduled.selector.MessageSelectorFactory;
22+
import com.github.imdmk.automessage.shared.message.MessageConfig;
23+
import com.github.imdmk.automessage.shared.message.MessageService;
24+
import com.github.imdmk.automessage.shared.validate.Validator;
25+
import dev.rollczi.litecommands.LiteCommands;
26+
import dev.rollczi.litecommands.bukkit.LiteBukkitFactory;
27+
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
28+
import org.bstats.bukkit.Metrics;
29+
import org.bukkit.Server;
30+
import org.bukkit.plugin.Plugin;
31+
import org.jetbrains.annotations.NotNull;
32+
33+
final class AutoMessagePlugin {
34+
35+
private static final String PLUGIN_PREFIX = "AutoMessage";
36+
private static final int PLUGIN_METRICS_ID = 19487;
37+
38+
private final Plugin plugin;
39+
private final Server server;
40+
private final PluginLogger logger;
41+
42+
private ConfigManager configManager;
43+
44+
private BukkitAudiences bukkitAudiences;
45+
private MessageService messageService;
46+
private TaskScheduler taskScheduler;
47+
48+
private LiteCommands<?> liteCommands;
49+
private Metrics metrics;
50+
51+
public AutoMessagePlugin(
52+
@NotNull final Plugin plugin,
53+
@NotNull final Server server,
54+
@NotNull final PluginLogger logger
55+
) {
56+
this.plugin = Validator.notNull(plugin, "plugin");
57+
this.server = Validator.notNull(server, "server");
58+
this.logger = Validator.notNull(logger, "logger");
59+
}
60+
61+
AutoMessagePlugin(@NotNull final Plugin plugin) {
62+
this(plugin, plugin.getServer(), new BukkitPluginLogger(plugin));
63+
}
64+
65+
void enable(@NotNull PluginSettings settings) {
66+
Validator.notNull(settings, "settings");
67+
68+
configManager = new ConfigManager(logger, plugin.getDataFolder());
69+
configManager.createAll(settings.configs());
70+
71+
bukkitAudiences = BukkitAudiences.create(plugin);
72+
messageService = new MessageService(configManager.require(MessageConfig.class), bukkitAudiences);
73+
taskScheduler = new BukkitTaskScheduler(plugin, server.getScheduler());
74+
75+
final MessageDispatcherConfig messageDispatcherConfig = configManager.require(MessageDispatcherConfig.class);
76+
final ScheduledMessagesConfig scheduledMessagesConfig = configManager.require(ScheduledMessagesConfig.class);
77+
78+
final AudienceFilter audienceFilter = AudienceFilter.createDefault();
79+
final MessageSelector messageSelector = MessageSelectorFactory.create(messageDispatcherConfig.selector);
80+
81+
final MessageDispatcher messageDispatcher = new MessageDispatcher(
82+
messageService,
83+
messageSelector,
84+
audienceFilter,
85+
() -> scheduledMessagesConfig.messages
86+
);
87+
88+
MessageDispatcherTask messageDispatcherTask = new MessageDispatcherTask(server, messageDispatcherConfig, messageDispatcher);
89+
taskScheduler.runTimerAsync(messageDispatcherTask);
90+
91+
liteCommands = LiteBukkitFactory.builder(PLUGIN_PREFIX, plugin, server)
92+
.invalidUsage(new InvalidUsageHandlerImpl(messageService))
93+
.missingPermission(new MissingPermissionsHandlerImpl(messageService))
94+
.result(Notice.class, new NoticeResultHandlerImpl(messageService))
95+
96+
.commands(
97+
new DisableCommand(messageDispatcherConfig, messageService),
98+
new EnableCommand(messageDispatcherConfig, messageService),
99+
new ReloadCommand(logger, configManager, taskScheduler, messageService)
100+
)
101+
102+
.build();
103+
104+
metrics = new Metrics(plugin, PLUGIN_METRICS_ID);
105+
106+
logger.info("%s plugin enabled.", PLUGIN_PREFIX);
107+
}
108+
109+
void disable() {
110+
// Validator.ifNotNull(configManager, manager -> {
111+
// manager.saveAll();
112+
// manager.clearAll();
113+
// });
114+
Validator.ifNotNull(bukkitAudiences, BukkitAudiences::close);
115+
Validator.ifNotNull(taskScheduler, TaskScheduler::shutdown);
116+
Validator.ifNotNull(liteCommands, LiteCommands::unregister);
117+
Validator.ifNotNull(metrics, Metrics::shutdown);
118+
119+
logger.info("%s plugin disabled successfully.", PLUGIN_PREFIX);
120+
}
121+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.github.imdmk.automessage;
2+
3+
import com.github.imdmk.automessage.config.ConfigSection;
4+
5+
import java.util.List;
6+
7+
public interface PluginSettings {
8+
9+
List<Class<? extends ConfigSection>> configs();
10+
11+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.github.imdmk.automessage.command.dispatcher;
2+
3+
import com.github.imdmk.automessage.scheduled.dispatcher.MessageDispatcherConfig;
4+
import com.github.imdmk.automessage.shared.message.MessageService;
5+
import com.github.imdmk.automessage.shared.validate.Validator;
6+
import dev.rollczi.litecommands.annotations.command.Command;
7+
import dev.rollczi.litecommands.annotations.context.Context;
8+
import dev.rollczi.litecommands.annotations.execute.Execute;
9+
import dev.rollczi.litecommands.annotations.permission.Permission;
10+
import org.bukkit.command.CommandSender;
11+
import org.jetbrains.annotations.NotNull;
12+
13+
@Command(name = "automessage disable")
14+
@Permission("command.automessage.disable")
15+
public final class DisableCommand {
16+
17+
private final MessageDispatcherConfig dispatcherConfig;
18+
private final MessageService messageService;
19+
20+
public DisableCommand(
21+
@NotNull MessageDispatcherConfig dispatcherConfig,
22+
@NotNull MessageService messageService
23+
) {
24+
this.dispatcherConfig = Validator.notNull(dispatcherConfig, "dispatcherConfig");
25+
this.messageService = Validator.notNull(messageService, "messageService");
26+
}
27+
28+
@Execute
29+
void disable(@Context CommandSender sender) {
30+
if (!dispatcherConfig.isEnabled()) {
31+
messageService.send(sender, n -> n.dispatcherMessages.dispatcherAlreadyDisabled());
32+
return;
33+
}
34+
35+
dispatcherConfig.setEnabled(false);
36+
dispatcherConfig.save();
37+
38+
messageService.send(sender, n -> n.dispatcherMessages.dispatcherDisabled());
39+
}
40+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.github.imdmk.automessage.command.dispatcher;
2+
3+
import com.github.imdmk.automessage.scheduled.dispatcher.MessageDispatcherConfig;
4+
import com.github.imdmk.automessage.shared.message.MessageService;
5+
import com.github.imdmk.automessage.shared.validate.Validator;
6+
import dev.rollczi.litecommands.annotations.command.Command;
7+
import dev.rollczi.litecommands.annotations.context.Context;
8+
import dev.rollczi.litecommands.annotations.execute.Execute;
9+
import dev.rollczi.litecommands.annotations.permission.Permission;
10+
import org.bukkit.command.CommandSender;
11+
import org.jetbrains.annotations.NotNull;
12+
13+
@Command(name = "automessage enable")
14+
@Permission("command.automessage.enable")
15+
public final class EnableCommand {
16+
17+
private final MessageDispatcherConfig dispatcherConfig;
18+
private final MessageService messageService;
19+
20+
public EnableCommand(
21+
@NotNull MessageDispatcherConfig dispatcherConfig,
22+
@NotNull MessageService messageService
23+
) {
24+
this.dispatcherConfig = Validator.notNull(dispatcherConfig, "dispatcherConfig");
25+
this.messageService = Validator.notNull(messageService, "messageService");
26+
}
27+
28+
@Execute
29+
void enable(@Context CommandSender sender) {
30+
if (dispatcherConfig.isEnabled()) {
31+
messageService.send(sender, n -> n.dispatcherMessages.dispatcherAlreadyEnabled());
32+
return;
33+
}
34+
35+
dispatcherConfig.setEnabled(true);
36+
dispatcherConfig.save();
37+
38+
messageService.send(sender, n -> n.dispatcherMessages.dispatcherEnabled());
39+
}
40+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.github.imdmk.automessage.command.dispatcher.messages;
2+
3+
import com.eternalcode.multification.notice.Notice;
4+
5+
public interface DispatcherMessages {
6+
7+
Notice dispatcherEnabled();
8+
9+
Notice dispatcherAlreadyEnabled();
10+
11+
Notice dispatcherDisabled();
12+
13+
Notice dispatcherAlreadyDisabled();
14+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package com.github.imdmk.automessage.command.dispatcher.messages;
2+
3+
import com.eternalcode.multification.notice.Notice;
4+
import eu.okaeri.configs.OkaeriConfig;
5+
import eu.okaeri.configs.annotation.Comment;
6+
7+
public final class DispatcherMessagesImpl
8+
extends OkaeriConfig
9+
implements DispatcherMessages {
10+
11+
@Comment({"#", "# Sent when automatic message dispatching is successfully enabled.", "#"})
12+
Notice dispatcherEnabled = Notice.chat(
13+
"<dark_gray>• <green>Automatic messages have been <bold>enabled</bold>.<dark_gray>"
14+
);
15+
16+
@Comment({"#", "# Sent when a user attempts to enable dispatching, but it is already active.", "#"})
17+
Notice dispatcherAlreadyEnabled = Notice.chat(
18+
"<dark_gray>• <yellow>Automatic messages are already enabled.<dark_gray>"
19+
);
20+
21+
@Comment({"#", "# Sent when automatic message dispatching is successfully disabled.", "#"})
22+
Notice dispatcherDisabled = Notice.chat(
23+
"<dark_gray>• <red>Automatic messages have been <bold>disabled</bold>.<dark_gray>"
24+
);
25+
26+
@Comment({"#", "# Sent when a user attempts to disable dispatching, but it is already inactive.", "#"})
27+
Notice dispatcherAlreadyDisabled = Notice.chat(
28+
"<dark_gray>• <yellow>Automatic messages are already disabled.<dark_gray>"
29+
);
30+
31+
@Override
32+
public Notice dispatcherEnabled() {
33+
return dispatcherEnabled;
34+
}
35+
36+
@Override
37+
public Notice dispatcherAlreadyEnabled() {
38+
return dispatcherAlreadyEnabled;
39+
}
40+
41+
@Override
42+
public Notice dispatcherDisabled() {
43+
return dispatcherDisabled;
44+
}
45+
46+
@Override
47+
public Notice dispatcherAlreadyDisabled() {
48+
return dispatcherAlreadyDisabled;
49+
}
50+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package com.github.imdmk.automessage.command.reload;
2+
3+
import com.github.imdmk.automessage.config.ConfigManager;
4+
import com.github.imdmk.automessage.platform.logger.PluginLogger;
5+
import com.github.imdmk.automessage.platform.scheduler.TaskScheduler;
6+
import com.github.imdmk.automessage.shared.message.MessageService;
7+
import com.github.imdmk.automessage.shared.validate.Validator;
8+
import dev.rollczi.litecommands.annotations.command.Command;
9+
import dev.rollczi.litecommands.annotations.context.Context;
10+
import dev.rollczi.litecommands.annotations.execute.Execute;
11+
import dev.rollczi.litecommands.annotations.permission.Permission;
12+
import org.bukkit.command.CommandSender;
13+
import org.jetbrains.annotations.NotNull;
14+
15+
@Command(name = "automessage reload")
16+
@Permission("command.automessage.reload")
17+
public final class ReloadCommand {
18+
19+
private final PluginLogger logger;
20+
private final ConfigManager configManager;
21+
private final TaskScheduler taskScheduler;
22+
private final MessageService messageService;
23+
24+
public ReloadCommand(
25+
@NotNull PluginLogger logger,
26+
@NotNull ConfigManager configManager,
27+
@NotNull TaskScheduler taskScheduler,
28+
@NotNull MessageService messageService
29+
) {
30+
this.logger = Validator.notNull(logger, "logger");
31+
this.configManager = Validator.notNull(configManager, "configManager");
32+
this.taskScheduler = Validator.notNull(taskScheduler, "taskScheduler");
33+
this.messageService = Validator.notNull(messageService, "messageService");
34+
}
35+
36+
@Execute
37+
void reload(@Context CommandSender sender) {
38+
taskScheduler.runAsync(() -> {
39+
try {
40+
configManager.loadAll();
41+
messageService.send(sender, n -> n.reloadMessages.configReloadedSuccess());
42+
} catch (Exception e) {
43+
logger.error(e, "Failed to reload plugin config");
44+
messageService.send(sender, n -> n.reloadMessages.configReloadFailed());
45+
}
46+
});
47+
}
48+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.github.imdmk.automessage.command.reload.messages;
2+
3+
import com.eternalcode.multification.notice.Notice;
4+
5+
public interface ReloadMessages {
6+
7+
Notice configReloadedSuccess();
8+
9+
Notice configReloadFailed();
10+
11+
}

0 commit comments

Comments
 (0)