Skip to content

Commit 28ef74a

Browse files
authored
chore: Improve maintainbility (#162)
2 parents 812938e + b300ff2 commit 28ef74a

28 files changed

+775
-524
lines changed

.github/workflows/build-pr.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ on: [pull_request]
33
permissions:
44
contents: write
55
checks: write
6+
issues: write
7+
pull-requests: write
68
jobs:
79
build_pr:
810
if: github.repository_owner == 'OneLiteFeatherNET'

.github/workflows/label-listener.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ name: PR Label Listener
22
permissions:
33
issues: write
44
actions: write
5+
pull-requests: write
56
on:
67
pull_request:
78
types: [labeled, unlabeled]

src/main/java/net/onelitefeather/antiredstoneclockremastered/AntiRedstoneClockRemastered.java

Lines changed: 22 additions & 268 deletions
Original file line numberDiff line numberDiff line change
@@ -2,310 +2,64 @@
22

33
import com.google.inject.Guice;
44
import com.google.inject.Injector;
5-
import io.papermc.paper.ServerBuildInfo;
5+
import com.google.inject.Stage;
66
import net.kyori.adventure.text.Component;
77
import net.kyori.adventure.text.minimessage.MiniMessage;
8-
import net.kyori.adventure.util.UTF8ResourceBundleControl;
9-
import net.onelitefeather.antiredstoneclockremastered.api.PlotsquaredSupport;
10-
import net.onelitefeather.antiredstoneclockremastered.api.WorldGuardSupport;
11-
import net.onelitefeather.antiredstoneclockremastered.commands.DisplayActiveClocksCommand;
12-
import net.onelitefeather.antiredstoneclockremastered.commands.FeatureCommand;
13-
import net.onelitefeather.antiredstoneclockremastered.commands.ReloadCommand;
8+
import net.onelitefeather.antiredstoneclockremastered.injection.MetricsModule;
9+
import net.onelitefeather.antiredstoneclockremastered.injection.CommandFrameworkModule;
1410
import net.onelitefeather.antiredstoneclockremastered.injection.CommandModule;
1511
import net.onelitefeather.antiredstoneclockremastered.injection.ExternalSupportModule;
1612
import net.onelitefeather.antiredstoneclockremastered.injection.ListenerModule;
1713
import net.onelitefeather.antiredstoneclockremastered.injection.PlatformModule;
1814
import net.onelitefeather.antiredstoneclockremastered.injection.ServiceModule;
19-
import net.onelitefeather.antiredstoneclockremastered.listener.*;
20-
import net.onelitefeather.antiredstoneclockremastered.plotsquared.v6.PlotSquaredLegacySupport;
21-
import net.onelitefeather.antiredstoneclockremastered.plotsquared.v7.PlotSquaredModernSupport;
22-
import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockService;
23-
import net.onelitefeather.antiredstoneclockremastered.service.factory.RedstoneClockServiceFactory;
15+
import net.onelitefeather.antiredstoneclockremastered.injection.TranslationModule;
2416
import net.onelitefeather.antiredstoneclockremastered.service.UpdateService;
25-
import net.onelitefeather.antiredstoneclockremastered.service.api.TranslationService;
26-
import net.onelitefeather.antiredstoneclockremastered.service.impl.LegacyTranslationService;
27-
import net.onelitefeather.antiredstoneclockremastered.service.impl.ModernTranslationService;
2817
import net.onelitefeather.antiredstoneclockremastered.utils.CheckTPS;
29-
import net.onelitefeather.antiredstoneclockremastered.worldguard.v6.WorldGuardLegacySupport;
30-
import net.onelitefeather.antiredstoneclockremastered.worldguard.v7.WorldGuardModernSupport;
31-
import org.bstats.bukkit.Metrics;
32-
import org.bstats.charts.DrilldownPie;
33-
import org.bstats.charts.SimplePie;
34-
import org.bukkit.Material;
35-
import org.bukkit.command.CommandSender;
36-
import org.bukkit.plugin.Plugin;
3718
import org.bukkit.plugin.java.JavaPlugin;
38-
import org.incendo.cloud.annotations.AnnotationParser;
39-
import org.incendo.cloud.bukkit.CloudBukkitCapabilities;
40-
import org.incendo.cloud.component.DefaultValue;
41-
import org.incendo.cloud.execution.ExecutionCoordinator;
42-
import org.incendo.cloud.minecraft.extras.MinecraftHelp;
43-
import org.incendo.cloud.minecraft.extras.RichDescription;
44-
import org.incendo.cloud.paper.LegacyPaperCommandManager;
4519

46-
import java.io.IOException;
47-
import java.net.URL;
48-
import java.net.URLClassLoader;
49-
import java.nio.file.Files;
50-
import java.nio.file.Path;
51-
import java.util.*;
52-
53-
import static org.incendo.cloud.parser.standard.StringParser.greedyStringParser;
20+
import java.util.Arrays;
5421

5522
public final class AntiRedstoneClockRemastered extends JavaPlugin {
56-
public static final String RESOURCE_BUNDLE_NAME = "antiredstoneclockremasterd";
5723

5824
// Injector for dependency injection
5925
private Injector injector;
60-
61-
// Legacy dependencies that are still manually managed
62-
private CheckTPS tps;
63-
private RedstoneClockService redstoneClockService;
64-
private WorldGuardSupport worldGuardSupport;
65-
private PlotsquaredSupport plotsquaredSupport;
66-
private Metrics metrics;
67-
private AnnotationParser<CommandSender> annotationParser;
68-
private UpdateService updateService;
6926

7027
public static final Component PREFIX = MiniMessage.miniMessage().deserialize("<gradient:red:white>[AntiRedstoneClock]</gradient>");
7128

7229
@Override
7330
public void onLoad() {
7431
saveDefaultConfig();
7532
reloadConfig();
76-
injector = Guice.createInjector(
77-
new PlatformModule(this),
78-
new ServiceModule(this),
79-
new ExternalSupportModule(this),
80-
new CommandModule(),
81-
new ListenerModule()
33+
injector = Guice.createInjector(Stage.PRODUCTION, Arrays.asList(
34+
new PlatformModule(this),
35+
new TranslationModule(),
36+
new ServiceModule(),
37+
new ExternalSupportModule(),
38+
new CommandModule(),
39+
new ListenerModule()
40+
)
8241
);
83-
this.worldGuardSupport = injector.getInstance(WorldGuardSupport.class);
8442
}
8543

8644
@Override
8745
public void onEnable() {
88-
TranslationService translationService = injector.getInstance(TranslationService.class);
89-
this.redstoneClockService = injector.getInstance(RedstoneClockService.class);
90-
this.updateService = injector.getInstance(UpdateService.class);
91-
this.tps = injector.getInstance(CheckTPS.class);
92-
this.plotsquaredSupport = injector.getInstance(PlotsquaredSupport.class);
93-
94-
// Setup translations
95-
Path langFolder = getDataFolder().toPath().resolve("lang");
96-
if (Files.notExists(langFolder)) {
97-
try {
98-
Files.createDirectories(langFolder);
99-
} catch (IOException e) {
100-
getSLF4JLogger().error("An error occurred while creating lang folder");
101-
return;
102-
}
103-
}
104-
var languages = new HashSet<>(getConfig().getStringList("translations"));
105-
languages.add("en-US");
106-
languages.stream()
107-
.map(Locale::forLanguageTag)
108-
.forEach(locale -> loadAndRegisterTranslation(locale, langFolder, translationService));
109-
translationService.registerGlobal();
110-
111-
// Initialize other components
46+
injector.getInstance(TranslationModule.class);
47+
injector.getInstance(CheckTPS.class).startCheck();
11248
donationInformation();
113-
updateService();
114-
enableCommandFramework();
115-
enableTPSChecker();
116-
enableBStatsSupport();
117-
registerEvents();
118-
registerCommands();
49+
injector.getInstance(UpdateService.class).schedule();
50+
injector.getInstance(UpdateService.class).run();
51+
injector.getInstance(UpdateService.class).notifyConsole(getComponentLogger());
52+
injector.getInstance(CommandFrameworkModule.class).enable();
53+
injector.getInstance(MetricsModule.class).registerCharts();
54+
this.injector.getInstance(ListenerModule.class).registerEvents(injector, this);
11955
}
120-
121-
private void updateService() {
122-
this.updateService.run();
123-
this.updateService.notifyConsole(getComponentLogger());
124-
}
125-
12656
@Override
12757
public void onDisable() {
128-
if (this.updateService != null) {
129-
this.updateService.shutdown();
130-
}
58+
injector.getInstance(UpdateService.class).shutdown();
13159
}
13260

13361
private void donationInformation() {
13462
getComponentLogger().info(Component.translatable("antiredstoneclockremastered.notify.donation.console"));
13563
}
13664

137-
private void registerCommands() {
138-
if (this.annotationParser != null) {
139-
this.annotationParser.parse(injector.getInstance(ReloadCommand.class));
140-
this.annotationParser.parse(injector.getInstance(DisplayActiveClocksCommand.class));
141-
this.annotationParser.parse(injector.getInstance(FeatureCommand.class));
142-
}
143-
}
144-
145-
private void enableCommandFramework() {
146-
LegacyPaperCommandManager<CommandSender> commandManager = LegacyPaperCommandManager.createNative(
147-
this,
148-
ExecutionCoordinator.asyncCoordinator()
149-
);
150-
if (commandManager.hasCapability(CloudBukkitCapabilities.NATIVE_BRIGADIER)) {
151-
commandManager.registerBrigadier();
152-
}
153-
else if (commandManager.hasCapability(CloudBukkitCapabilities.ASYNCHRONOUS_COMPLETION)) {
154-
commandManager.registerAsynchronousCompletions();
155-
}
156-
annotationParser = new AnnotationParser<>(commandManager, CommandSender.class);
157-
annotationParser.descriptionMapper(string -> RichDescription.of(Component.translatable(string)));
158-
MinecraftHelp<CommandSender> help = MinecraftHelp.create(
159-
"/arcm help",
160-
commandManager,
161-
sender -> sender
162-
);
163-
commandManager.command(
164-
commandManager.commandBuilder("arcm").literal("help")
165-
.permission("antiredstoneclockremastered.command.help")
166-
.optional("query", greedyStringParser(), DefaultValue.constant(""))
167-
.handler(context -> {
168-
help.queryCommands(context.get("query"), context.sender());
169-
})
170-
);
171-
}
172-
173-
// External support now handled by DI in ExternalSupportModule
174-
175-
private void registerEvents() {
176-
// Register DI-enabled listeners
177-
getServer().getPluginManager().registerEvents(injector.getInstance(PlayerListener.class), this);
178-
179-
if (getConfig().getBoolean("check.observer", true)) {
180-
getServer().getPluginManager().registerEvents(injector.getInstance(ObserverListener.class), this);
181-
}
182-
183-
if (getConfig().getBoolean("check.sculk", true)) {
184-
var sculk = Material.getMaterial("SCULK");
185-
if (sculk != null) {
186-
getServer().getPluginManager().registerEvents(injector.getInstance(SculkListener.class), this);
187-
}
188-
}
189-
190-
if (getConfig().getBoolean("check.piston", true)) {
191-
getServer().getPluginManager().registerEvents(injector.getInstance(PistonListener.class), this);
192-
}
193-
194-
// Material-dependent listeners now use dependency injection
195-
if (getConfig().getBoolean("check.comparator", true)) {
196-
var comparator = Material.getMaterial("COMPARATOR");
197-
if (comparator != null) {
198-
var listener = injector.getInstance(ListenerModule.class)
199-
.createComparatorListener(comparator, redstoneClockService, tps, this);
200-
getServer().getPluginManager().registerEvents(listener, this);
201-
} else {
202-
var listener1 = injector.getInstance(ListenerModule.class)
203-
.createComparatorListener(Material.getMaterial("REDSTONE_COMPARATOR_OFF"), redstoneClockService, tps, this);
204-
var listener2 = injector.getInstance(ListenerModule.class)
205-
.createComparatorListener(Material.getMaterial("REDSTONE_COMPARATOR_ON"), redstoneClockService, tps, this);
206-
getServer().getPluginManager().registerEvents(listener1, this);
207-
getServer().getPluginManager().registerEvents(listener2, this);
208-
}
209-
}
210-
211-
if (getConfig().getBoolean("check.redstoneAndRepeater", true)) {
212-
var repeater = Material.getMaterial("REPEATER");
213-
if (repeater != null) {
214-
var listener = injector.getInstance(ListenerModule.class)
215-
.createRedstoneListener(repeater, redstoneClockService, tps, this);
216-
getServer().getPluginManager().registerEvents(listener, this);
217-
} else {
218-
var listener1 = injector.getInstance(ListenerModule.class)
219-
.createRedstoneListener(Material.getMaterial("DIODE_BLOCK_ON"), redstoneClockService, tps, this);
220-
var listener2 = injector.getInstance(ListenerModule.class)
221-
.createRedstoneListener(Material.getMaterial("DIODE_BLOCK_OFF"), redstoneClockService, tps, this);
222-
getServer().getPluginManager().registerEvents(listener1, this);
223-
getServer().getPluginManager().registerEvents(listener2, this);
224-
}
225-
}
226-
}
227-
228-
private void enableTPSChecker() {
229-
this.tps.startCheck();
230-
}
231-
232-
private void enableBStatsSupport() {
233-
this.metrics = new Metrics(this, 19085);
234-
this.metrics.addCustomChart(new SimplePie("worldguard", this::bstatsWorldGuardVersion));
235-
this.metrics.addCustomChart(new SimplePie("plotsquared", this::bstatsPlotSquaredVersion));
236-
this.metrics.addCustomChart(new DrilldownPie("maxcount", this::bstatsMaxCount));
237-
}
238-
239-
private Map<String, Map<String, Integer>> bstatsMaxCount() {
240-
var map = new HashMap<String, Map<String, Integer>>();
241-
var count = getConfig().getInt("clock.maxCount");
242-
var entry = Map.of(String.valueOf(count), 1);
243-
switch (count) {
244-
case 0 -> map.put("0 \uD83D\uDEAB", entry);
245-
case 1, 2, 3, 4, 5 -> map.put("1-5 \uD83D\uDE10", entry);
246-
case 6, 7, 8, 9, 10 -> map.put("6-10 \uD83D\uDE42", entry);
247-
case 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 -> map.put("11-25 \uD83D\uDE0A", entry);
248-
case 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50 ->
249-
map.put("26-50 \uD83D\uDE00", entry);
250-
default -> map.put("50+ \uD83D\uDE01", entry);
251-
}
252-
return map;
253-
}
254-
255-
private String bstatsPlotSquaredVersion() {
256-
if (this.plotsquaredSupport != null) {
257-
return this.plotsquaredSupport.getVersion();
258-
}
259-
return "unknown";
260-
}
261-
262-
private String bstatsWorldGuardVersion() {
263-
if (this.worldGuardSupport != null) {
264-
return this.worldGuardSupport.getVersion();
265-
}
266-
return "unknown";
267-
}
268-
269-
private void loadAndRegisterTranslation(Locale locale, Path langFolder, TranslationService translationService) {
270-
try {
271-
ResourceBundle bundle = loadResourceBundle(locale, langFolder);
272-
if (bundle != null) {
273-
translationService.registerAll(locale, bundle, false);
274-
}
275-
} catch (Exception e) {
276-
getSLF4JLogger().error("An error occurred while loading language file for locale {}", locale, e);
277-
}
278-
}
279-
280-
private ResourceBundle loadResourceBundle(Locale locale, Path langFolder) throws Exception {
281-
Path langFile = langFolder.resolve(RESOURCE_BUNDLE_NAME + "_" + locale.toLanguageTag() + ".properties");
282-
283-
if (Files.exists(langFile)) {
284-
try (URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{langFolder.toUri().toURL()})) {
285-
return ResourceBundle.getBundle(RESOURCE_BUNDLE_NAME, locale, urlClassLoader, UTF8ResourceBundleControl.get());
286-
}
287-
} else {
288-
return ResourceBundle.getBundle(RESOURCE_BUNDLE_NAME, locale, UTF8ResourceBundleControl.get());
289-
}
290-
}
291-
292-
public CheckTPS getTps() {
293-
return tps;
294-
}
295-
296-
public RedstoneClockService getRedstoneClockService() {
297-
return redstoneClockService;
298-
}
299-
300-
public WorldGuardSupport getWorldGuardSupport() {
301-
return worldGuardSupport;
302-
}
303-
304-
public PlotsquaredSupport getPlotsquaredSupport() {
305-
return plotsquaredSupport;
306-
}
307-
308-
public UpdateService getUpdateService() {
309-
return updateService;
310-
}
31165
}

0 commit comments

Comments
 (0)