mirror of
https://github.com/CivMC/Civ.git
synced 2026-07-15 23:20:44 +00:00
add restart announcements
This commit is contained in:
@@ -38,6 +38,8 @@ dependencies {
|
|||||||
pvpPlugin(project(path = ":plugins:namelayer-paper"))
|
pvpPlugin(project(path = ":plugins:namelayer-paper"))
|
||||||
pvpPlugin(project(path = ":plugins:civchat2-paper"))
|
pvpPlugin(project(path = ":plugins:civchat2-paper"))
|
||||||
pvpPlugin(project(path = ":plugins:namecolors-paper"))
|
pvpPlugin(project(path = ":plugins:namecolors-paper"))
|
||||||
|
|
||||||
|
proxyPlugin(project(path = ":plugins:announcements-velocity", configuration = "shadow"))
|
||||||
}
|
}
|
||||||
|
|
||||||
val copyPaperPlugins = tasks.register<Copy>("copyPaperPlugins") {
|
val copyPaperPlugins = tasks.register<Copy>("copyPaperPlugins") {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
paper = "1.21.3-R0.1-SNAPSHOT"
|
paper = "1.21.3-R0.1-SNAPSHOT"
|
||||||
junit = "5.8.2"
|
junit = "5.8.2"
|
||||||
nuotifier = "2.7.2"
|
nuotifier = "2.7.2"
|
||||||
|
velocity = "3.4.0-SNAPSHOT"
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
paper-userdev = { id = "io.papermc.paperweight.userdev", version = "2.0.0-beta.11" }
|
paper-userdev = { id = "io.papermc.paperweight.userdev", version = "2.0.0-beta.11" }
|
||||||
@@ -10,6 +11,7 @@ runpaper = { id = "xyz.jpenilla.run-paper", version = "2.3.1" }
|
|||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
paper-api = { group = "io.papermc.paper", name = "paper-api", version.ref = "paper" }
|
paper-api = { group = "io.papermc.paper", name = "paper-api", version.ref = "paper" }
|
||||||
|
velocity-api = { group = "com.velocitypowered", name = "velocity-api", version.ref = "velocity"}
|
||||||
|
|
||||||
aikar-acf = { group = "co.aikar", name = "acf-bukkit", version = "0.5.1-SNAPSHOT" }
|
aikar-acf = { group = "co.aikar", name = "acf-bukkit", version = "0.5.1-SNAPSHOT" }
|
||||||
aikar-taskchain = { group = "co.aikar", name = "taskchain-bukkit", version = "3.7.2" }
|
aikar-taskchain = { group = "co.aikar", name = "taskchain-bukkit", version = "3.7.2" }
|
||||||
@@ -18,6 +20,9 @@ commons-lang3 = { group = "org.apache.commons", name = "commons-lang3", version
|
|||||||
commons-collections4 = { group = "org.apache.commons", name = "commons-collections4", version = "4.4" }
|
commons-collections4 = { group = "org.apache.commons", name = "commons-collections4", version = "4.4" }
|
||||||
commons-math3 = { group = "org.apache.commons", name = "commons-math3", version = "3.6.1" }
|
commons-math3 = { group = "org.apache.commons", name = "commons-math3", version = "3.6.1" }
|
||||||
|
|
||||||
|
cron-utils = { group = "com.cronutils", name = "cron-utils", version = "9.2.1" }
|
||||||
|
snakeyaml = { group = "org.yaml", name = "snakeyaml", version = "2.3"}
|
||||||
|
|
||||||
rabbitmq-client = { group = "com.rabbitmq", name = "amqp-client", version = "5.17.1" }
|
rabbitmq-client = { group = "com.rabbitmq", name = "amqp-client", version = "5.17.1" }
|
||||||
|
|
||||||
nuvotifier-api = { group = "com.github.NuVotifier.NuVotifier", name = "nuvotifier-api", version.ref = "nuotifier" }
|
nuvotifier-api = { group = "com.github.NuVotifier.NuVotifier", name = "nuvotifier-api", version.ref = "nuotifier" }
|
||||||
|
|||||||
13
plugins/announcements-velocity/build.gradle.kts
Normal file
13
plugins/announcements-velocity/build.gradle.kts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
plugins {
|
||||||
|
id("com.github.johnrengelman.shadow")
|
||||||
|
}
|
||||||
|
|
||||||
|
version = "1.0.0"
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compileOnly(libs.velocity.api)
|
||||||
|
annotationProcessor(libs.velocity.api)
|
||||||
|
|
||||||
|
implementation(libs.cron.utils)
|
||||||
|
implementation(libs.snakeyaml)
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package net.civmc.announcements;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @implNote property must be named the same as in the config file, must also have getters and setters else snakeyaml doesn't like it
|
||||||
|
*/
|
||||||
|
public class AnnouncementsConfig {
|
||||||
|
|
||||||
|
public static class ScheduledAnnouncement {
|
||||||
|
private String cron;
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
public void setMessage(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
public String getCron() {
|
||||||
|
return cron;
|
||||||
|
}
|
||||||
|
public void setCron(String cron) {
|
||||||
|
this.cron = cron;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ScheduledAnnouncement> scheduledAnnouncements;
|
||||||
|
|
||||||
|
public List<ScheduledAnnouncement> getScheduledAnnouncements() {
|
||||||
|
return scheduledAnnouncements;
|
||||||
|
}
|
||||||
|
public void setScheduledAnnouncements(List<ScheduledAnnouncement> scheduledAnnouncements) {
|
||||||
|
this.scheduledAnnouncements = scheduledAnnouncements;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
package net.civmc.announcements;
|
||||||
|
|
||||||
|
import com.cronutils.model.Cron;
|
||||||
|
import com.cronutils.model.CronType;
|
||||||
|
import com.cronutils.model.definition.CronDefinitionBuilder;
|
||||||
|
import com.cronutils.model.time.ExecutionTime;
|
||||||
|
import com.cronutils.parser.CronParser;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.velocitypowered.api.event.Subscribe;
|
||||||
|
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
|
||||||
|
import com.velocitypowered.api.plugin.Plugin;
|
||||||
|
import com.velocitypowered.api.plugin.annotation.DataDirectory;
|
||||||
|
import com.velocitypowered.api.proxy.ProxyServer;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.serializer.json.JSONComponentSerializer;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.yaml.snakeyaml.LoaderOptions;
|
||||||
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
import org.yaml.snakeyaml.constructor.Constructor;
|
||||||
|
|
||||||
|
@Plugin(id = "civannouncements", name = "Civ Announcements", version = "1.0.0",
|
||||||
|
url = "https://civmc.net", description = "Sends various announcements", authors = {"Huskydog9988"})
|
||||||
|
public class AnnouncementsPlugin {
|
||||||
|
|
||||||
|
private final CronParser parser = new CronParser(CronDefinitionBuilder.instanceDefinitionFor(CronType.UNIX));
|
||||||
|
|
||||||
|
private final ProxyServer server;
|
||||||
|
private final Logger logger;
|
||||||
|
private final Path dataDirectory;
|
||||||
|
|
||||||
|
private final Map<Cron, Component> scheduledAnnouncements = new ConcurrentHashMap<>();
|
||||||
|
private AnnouncementsConfig config;
|
||||||
|
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public AnnouncementsPlugin(ProxyServer server, Logger logger, @DataDirectory Path dataDirectory) {
|
||||||
|
this.server = server;
|
||||||
|
this.logger = logger;
|
||||||
|
this.dataDirectory = dataDirectory;
|
||||||
|
|
||||||
|
logger.info("Initializing Announcements plugin");
|
||||||
|
|
||||||
|
loadConfig();
|
||||||
|
scheduleTasks();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scheduleTasks() {
|
||||||
|
var serializer = JSONComponentSerializer.json();
|
||||||
|
|
||||||
|
// ensure config exists
|
||||||
|
if (config == null) {
|
||||||
|
logger.info("Config is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (AnnouncementsConfig.ScheduledAnnouncement item : config.getScheduledAnnouncements()) {
|
||||||
|
Cron cron = parser.parse(item.getCron());
|
||||||
|
// convert json message to Component
|
||||||
|
var formatedMsg = serializer.deserialize(item.getMessage());
|
||||||
|
|
||||||
|
scheduledAnnouncements.put(cron, formatedMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onProxyInitialization(ProxyInitializeEvent event) {
|
||||||
|
// when server is initialized, register listeners
|
||||||
|
server.getEventManager().register(this, new ProxyListener());
|
||||||
|
|
||||||
|
// task to check if a scheduled announcement should be sent
|
||||||
|
server.getScheduler().buildTask(this, this::sendScheduledMessages).repeat(1, TimeUnit.SECONDS).schedule();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a scheduled message needs to be sent, and sends them if so
|
||||||
|
*/
|
||||||
|
private void sendScheduledMessages() {
|
||||||
|
ZonedDateTime now = ZonedDateTime.now();
|
||||||
|
|
||||||
|
for (Cron cron : scheduledAnnouncements.keySet()) {
|
||||||
|
var executionTime = ExecutionTime.forCron(cron);
|
||||||
|
|
||||||
|
// if now is a time the
|
||||||
|
if (executionTime.isMatch(now)) {
|
||||||
|
server.sendMessage(scheduledAnnouncements.get(cron));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the config from disk, and creates it if necessary
|
||||||
|
*/
|
||||||
|
private void loadConfig() {
|
||||||
|
try {
|
||||||
|
if (!Files.exists(dataDirectory)) {
|
||||||
|
Files.createDirectories(dataDirectory);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("Could not create data directory: {}", dataDirectory, e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Path configFile = dataDirectory.resolve("config.yml");
|
||||||
|
if (!Files.exists(configFile)) {
|
||||||
|
try (InputStream in = getClass().getResourceAsStream("/config.yml")) {
|
||||||
|
if (in != null) {
|
||||||
|
Files.copy(in, configFile);
|
||||||
|
logger.info("Default configuration file created.");
|
||||||
|
} else {
|
||||||
|
logger.error("Default configuration file is missing in resources!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("Could not create default configuration file: {}", configFile, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try (InputStream in = Files.newInputStream(configFile)) {
|
||||||
|
// register config class with snakeyaml so it knows how to populate the config
|
||||||
|
Yaml yaml = new Yaml(new Constructor(AnnouncementsConfig.class, new LoaderOptions()));
|
||||||
|
config = yaml.load(in);
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("Could not read config file: {}", configFile, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package net.civmc.announcements;
|
||||||
|
|
||||||
|
public class ProxyListener {
|
||||||
|
|
||||||
|
}
|
||||||
10
plugins/announcements-velocity/src/main/resources/config.yml
Normal file
10
plugins/announcements-velocity/src/main/resources/config.yml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
# messages must be in json format
|
||||||
|
# https://minecraft.tools/en/json_text.php
|
||||||
|
scheduledAnnouncements:
|
||||||
|
- cron: "45 1 * * *"
|
||||||
|
message: "{\"text\":\"Restart in 15 minutes\",\"color\":\"gold\"}"
|
||||||
|
- cron: "55 1 * * *"
|
||||||
|
message: "{\"text\":\"Restart in 5 minutes\",\"color\":\"gold\"}"
|
||||||
|
- cron: "59 1 * * *"
|
||||||
|
message: "{\"text\":\"Restart in 1 minute\",\"color\":\"gold\"}"
|
||||||
@@ -13,6 +13,7 @@ plugins {
|
|||||||
|
|
||||||
include(":ansible")
|
include(":ansible")
|
||||||
|
|
||||||
|
include(":plugins:announcements-velocity")
|
||||||
include(":plugins:banstick-paper")
|
include(":plugins:banstick-paper")
|
||||||
include(":plugins:bastion-paper")
|
include(":plugins:bastion-paper")
|
||||||
include(":plugins:castlegates-paper")
|
include(":plugins:castlegates-paper")
|
||||||
|
|||||||
Reference in New Issue
Block a user