Compare commits

..
63 Commits
Author SHA1 Message Date
KennyTV 3b4a66b04e 2.5 Release 2018-11-17 11:46:04 +01:00
KennyTV 7384b2e55c 2.5 API 2018-11-17 11:44:28 +01:00
KennyTV f8eaed445a Version increase to 2.5 2018-11-17 11:43:43 +01:00
KennyTV dfef9190ca Some final fixes and changes 2018-11-17 11:41:51 +01:00
KennyTV 7ce61834c2 Check for other kick reasons 2018-11-16 22:23:58 +01:00
KennyTV 240a7ab242 Message changes 2018-11-16 22:08:35 +01:00
KennyTV b3de59bfba API change 2018-11-10 22:08:29 +01:00
KennyTV 5d5de39845 Make the help message a little fancier 2018-11-10 17:38:41 +01:00
KennyTV 59af774d09 Some more fixes 2018-11-10 16:50:10 +01:00
KennyTV 18828207c0 Maintenance status command + some more minor changes 2018-11-10 15:08:32 +01:00
KennyTV 5c67922996 Some fixes and changes 2018-11-09 23:20:34 +01:00
KennyTV af50a45e65 Command 2018-11-09 21:14:32 +01:00
KennyTV 7ccd265a30 pom changes 2018-11-07 21:36:29 +01:00
KennyTV e76f22f071 Timer commands for single server maintenance 2018-11-07 21:32:08 +01:00
KennyTV 3c03b719d2 API changes 2018-11-07 21:31:49 +01:00
KennyTV cd71531766 Timers for single server maintenance
Todo: Implementation in command
2018-11-07 20:02:59 +01:00
KennyTV 282c116d02 Some improvements to messages and message handling 2018-11-06 11:01:04 +01:00
KennyTV 820171916b Improve version check handling 2018-11-05 23:02:46 +01:00
KennyTV 136fbb0ba8 Improve version check handling 2018-11-05 22:58:12 +01:00
KennyTV 4f0c05c357 Further single server maintenance stuff 2018-11-05 21:24:56 +01:00
KennyTV 0377838a26 Dont save and get Spigot maintenance servers from sql for now 2018-11-04 14:43:47 +01:00
KennyTV b72ff1b772 Some message changes 2018-10-19 14:21:21 +02:00
KennyTV 287488f1b6 Some single server maintenance stuff I did during a course at university ¯\_(ツ)_/¯ 2018-10-19 12:08:37 +02:00
KennyTV 9ffb67db1f WIP: Add possibility to set single servers to maintenance 2018-10-12 23:17:46 +02:00
KennyTV a563c0a8a8 Restructured language files 2018-10-02 12:15:08 +02:00
KennyTV 234086444f WIP: Add possibility to set single servers to maintenance 2018-10-02 11:56:30 +02:00
KennyTV a93b0834a2 Remove more or less deprecated Guava usages 2018-09-30 11:29:48 +02:00
KennyTV b5550dfe82 Add multiple language support 2018-09-28 13:22:55 +02:00
KennyTV d99300ecac Version increase to 2.5-SNAPSHOT
Increase from 2.4.1-SNAPSHOT as bigger feature updates are planned
2018-09-28 12:42:06 +02:00
KennyTV 1c0688a172 Add language-de 2018-09-28 12:00:40 +02:00
KennyTV ff3b117189 Make SenderInfo an interface instead of an abstract class 2018-09-27 10:14:29 +02:00
KennyTV aaed1b32cd Fix starttimer command not working
Remove slf4j shade for now
2018-09-27 09:57:56 +02:00
KennyTV 38c8e1d2c3 Shade slf4j to fix compatibility with plugins using older Hikari dependencies 2018-09-26 11:11:56 +02:00
KennyTV 1e1792d132 Version increase to 2.4.1-SNAPSHOT
Update ProtocolLib dependency to newest release
2018-09-22 19:20:55 +02:00
KennyTV b29462a5cb 2.4 Release 2018-09-17 10:21:17 +02:00
KennyTV c9161ebe24 2.4 Release API 2018-09-17 10:17:44 +02:00
KennyTV 8441c6a8bf Prepare for 2.4 Release 2018-09-17 10:16:23 +02:00
KennyTV 72c2ba77ee Some final fixes and changes
Move kickmessage back to config
2018-09-16 22:36:12 +02:00
KennyTV a097790b76 Update dependencies 2018-09-13 10:43:09 +02:00
KennyTV b7129e8aa8 Fix raw color saving in config when upgrading from a version lower than 2.3 2018-09-08 12:29:10 +02:00
KennyTV ab9c2b8be1 Spigot Runnable fix 2018-09-08 12:13:47 +02:00
KennyTV a9a37b8fc8 Fix Bungee config not updating 2018-09-08 12:00:21 +02:00
KennyTV d50cb67a26 Add timer variable for the pingmessage
Have broadcasts for timers be set for seconds instead of just minutes + better formatting
Some language fixes
2018-09-07 22:52:20 +02:00
KennyTV 5e42500308 WIP: Add timer variable for the pingmessage
WIP: Have broadcasts for timers be set for seconds instead of just minutes + better formatting
2018-08-29 00:42:00 +02:00
KennyTV 50997a847f Language fixes and changes 2018-08-26 17:56:31 +02:00
KennyTV 2305d85c01 Switch messages to language file + small fixes 2018-08-26 12:34:28 +02:00
KennyTV 33bbc35d88 Change javadoc message to read the new config field 2018-08-26 11:50:08 +02:00
KennyTV 28b3e100fb Switch some more messages to language file 2018-08-26 11:49:13 +02:00
KennyTV edae2d699b Switch some messages to language file 2018-08-25 12:37:23 +02:00
KennyTV 0cc477a769 Prepare new language file 2018-08-25 12:19:01 +02:00
KennyTV 53b84a999f Change helpmessage 2018-08-25 11:41:33 +02:00
KennyTV 49487c11ff Don't enable/disable maintenance mode if it's already in the goal's state 2018-08-25 11:39:49 +02:00
KennyTV 0c4070b7a7 Add possibility to show the default playercount 2018-08-22 20:11:24 +02:00
KennyTV 67909a4862 Relocate HikariCP dependency 2018-08-22 19:08:20 +02:00
KennyTV 28ee563083 Don't spam update notifications on every single join
Also, minor cleanup #3
2018-08-21 21:05:48 +02:00
KennyTV 28b2b528c1 Minor cleanup #2 2018-08-21 21:01:12 +02:00
KennyTV a53d9d0850 Minor cleanup 2018-08-21 20:58:59 +02:00
KennyTV 873a8812aa Add variables to show normal playercount 2018-08-21 20:53:15 +02:00
KennyTV 19ebc90963 Whoops 2018-08-17 12:37:49 +02:00
KennyTV dfbd1381de Version increase to 2.4-SNAPSHOT 2018-08-17 12:36:08 +02:00
KennyTV c9fe48a067 2.3.1 Release
Hotfix before the release
2018-08-17 12:30:01 +02:00
KennyTV 49b022b665 Quick hotfix for the 2.3.1 Release
When enabling maintenance on one proxy with MySQL enabled, the other ones will now also kick all non permitted players and switch their ServerListPlus state
2018-08-17 11:29:28 +02:00
KennyTV 86be23ae5f Minor changes 2018-08-16 19:05:44 +02:00
40 changed files with 1221 additions and 398 deletions

No files matched your search

Binary file not shown.
+2 -2
View File
@@ -6,7 +6,7 @@
<parent>
<artifactId>maintenance-base</artifactId>
<groupId>eu.kennytv</groupId>
<version>2.3.1</version>
<version>2.5</version>
</parent>
<artifactId>maintenance-api</artifactId>
@@ -22,7 +22,7 @@
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.12.2-R0.1-SNAPSHOT</version>
<version>1.13.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
@@ -17,7 +17,7 @@ public interface ISettings {
boolean isMaintenance();
/**
* @return true if "join-notification" is set to true in the config
* @return true if "send-join-notification" is set to true in the config
*/
boolean isJoinNotifications();
@@ -0,0 +1,30 @@
package eu.kennytv.maintenance.api.bungee;
import eu.kennytv.maintenance.api.IMaintenance;
import net.md_5.bungee.api.config.ServerInfo;
/**
* @author KennyTV
* @since 2.5
*/
public interface IMaintenanceBungee extends IMaintenance {
/**
* Enables/disables maintenance mode on a proxied server.
* If enabled, all non-permitted players will be kicked.
* If MySQL is enabled, it will also be written into the database.
*
* @param maintenance true to enable, false to disable maintenance mode
*/
boolean setMaintenanceToServer(ServerInfo server, boolean maintenance);
/**
* @return true if maintenance is currently enabled on the proxied server
*/
boolean isMaintenance(ServerInfo server);
/**
* @return true if a start- or endtimer task is currently running regarding the proxied server
*/
boolean isServerTaskRunning(ServerInfo server);
}
@@ -1,29 +1,29 @@
package eu.kennytv.maintenance.api;
package eu.kennytv.maintenance.api.bungee;
import eu.kennytv.maintenance.api.IMaintenanceBase;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.plugin.Plugin;
/**
* Utility class to get the {@link IMaintenance} instance for the BungeeCord version of the plugin.
* Utility class to get the {@link IMaintenanceBungee} instance for the BungeeCord version of the plugin.
* <p>
* Only access this class if you're running the plugin on a BungeeCord server!
* </p>
*
* @author KennyTV
* @since 2.1
* @since 2.5
*/
public final class MaintenanceBungeeAPI {
/**
* Returns API instance of IMaintenance.
*
* @return {@link IMaintenance} instance
* @return {@link IMaintenanceBungee} instance
*/
public static IMaintenance getAPI() {
public static IMaintenanceBungee getAPI() {
final Plugin maintenance = ProxyServer.getInstance().getPluginManager().getPlugin("MaintenanceBungee");
if (maintenance == null)
ProxyServer.getInstance().getLogger().warning("Could not get instance of MaintenanceBungee!");
return ((IMaintenanceBase) maintenance).getApi();
return (IMaintenanceBungee) ((IMaintenanceBase) maintenance).getApi();
}
}
@@ -1,5 +1,7 @@
package eu.kennytv.maintenance.api;
package eu.kennytv.maintenance.api.spigot;
import eu.kennytv.maintenance.api.IMaintenance;
import eu.kennytv.maintenance.api.IMaintenanceBase;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
@@ -10,7 +12,7 @@ import org.bukkit.plugin.Plugin;
* </p>
*
* @author KennyTV
* @since 2.1
* @since 2.5
*/
public final class MaintenanceSpigotAPI {
@@ -23,7 +25,6 @@ public final class MaintenanceSpigotAPI {
final Plugin maintenance = Bukkit.getPluginManager().getPlugin("MaintenanceSpigot");
if (maintenance == null)
Bukkit.getLogger().warning("Could not get instance of MaintenanceSpigot!");
return ((IMaintenanceBase) maintenance).getApi();
}
}
+1 -1
View File
@@ -6,7 +6,7 @@
<parent>
<artifactId>maintenance-base</artifactId>
<groupId>eu.kennytv</groupId>
<version>2.3.1</version>
<version>2.5</version>
</parent>
<artifactId>maintenance-bungee</artifactId>
@@ -2,39 +2,52 @@ package eu.kennytv.maintenance.bungee;
import eu.kennytv.maintenance.api.IMaintenance;
import eu.kennytv.maintenance.api.ISettings;
import eu.kennytv.maintenance.api.MaintenanceBungeeAPI;
import eu.kennytv.maintenance.api.bungee.IMaintenanceBungee;
import eu.kennytv.maintenance.api.bungee.MaintenanceBungeeAPI;
import eu.kennytv.maintenance.bungee.command.MaintenanceBungeeCommand;
import eu.kennytv.maintenance.bungee.command.MaintenanceBungeeCommandBase;
import eu.kennytv.maintenance.bungee.listener.PostLoginListener;
import eu.kennytv.maintenance.bungee.listener.ServerConnectListener;
import eu.kennytv.maintenance.bungee.metrics.MetricsLite;
import eu.kennytv.maintenance.bungee.runnable.SingleMaintenanceRunnable;
import eu.kennytv.maintenance.core.MaintenanceModePlugin;
import eu.kennytv.maintenance.core.Settings;
import eu.kennytv.maintenance.core.hook.ServerListPlusHook;
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnableBase;
import eu.kennytv.maintenance.core.util.ServerType;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.api.plugin.PluginManager;
import net.minecrell.serverlistplus.core.plugin.ServerListPlusPlugin;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
/**
* @author KennyTV
* @since 1.0
*/
public final class MaintenanceBungeePlugin extends MaintenanceModePlugin {
public final class MaintenanceBungeePlugin extends MaintenanceModePlugin implements IMaintenanceBungee {
private final MaintenanceBungeeBase plugin;
private final SettingsBungee settings;
private final Map<String, Integer> serverTaskIds = new HashMap<>();
MaintenanceBungeePlugin(final MaintenanceBungeeBase plugin) {
super("§8[§eMaintenanceBungee§8] ", plugin.getDescription().getVersion());
super("§8[§eMaintenanceBungee§8] ", plugin.getDescription().getVersion(), ServerType.BUNGEE);
this.plugin = plugin;
plugin.getLogger().info("Plugin by KennyTV");
plugin.getLogger().info(getUpdateMessage());
settings = new SettingsBungee(plugin);
settings = new SettingsBungee(this, plugin);
final PluginManager pm = getProxy().getPluginManager();
pm.registerListener(plugin, new PostLoginListener(this, settings));
pm.registerListener(plugin, new ServerConnectListener(this, settings));
final MaintenanceBungeeCommand maintenanceCommand = new MaintenanceBungeeCommand(this, settings);
pm.registerCommand(plugin, new MaintenanceBungeeCommandBase(maintenanceCommand));
@@ -60,24 +73,80 @@ public final class MaintenanceBungeePlugin extends MaintenanceModePlugin {
settings.reloadConfigs();
}
if (serverListPlusHook != null)
serverListPlusHook.setEnabled(!maintenance);
serverActions(maintenance);
if (isTaskRunning())
cancelTask();
}
void serverActions(final boolean maintenance) {
if (serverListPlusHook != null)
serverListPlusHook.setEnabled(!maintenance);
if (maintenance) {
getProxy().getPlayers().stream()
.filter(p -> !p.hasPermission("maintenance.bypass") && !settings.getWhitelistedPlayers().containsKey(p.getUniqueId()))
.forEach(p -> p.disconnect(settings.getKickMessage().replace("%NEWLINE%", "\n")));
getProxy().broadcast(settings.getMaintenanceActivated());
getProxy().broadcast(settings.getMessage("maintenanceActivated"));
} else
getProxy().broadcast(settings.getMaintenanceDeactivated());
getProxy().broadcast(settings.getMessage("maintenanceDeactivated"));
}
@Override
public int schedule(final Runnable runnable) {
return getProxy().getScheduler().schedule(plugin, runnable, 0, 1, TimeUnit.MINUTES).getId();
public boolean isMaintenance(final ServerInfo server) {
return settings.getMaintenanceServers().contains(server.getName());
}
@Override
public boolean setMaintenanceToServer(final ServerInfo server, final boolean maintenance) {
if (maintenance) {
if (!settings.getMaintenanceServers().add(server.getName())) return false;
final ServerInfo fallback = getProxy().getServerInfo(settings.getFallbackServer());
if (fallback == null)
plugin.getLogger().warning("The fallback server set in the SpigotServers.yml could not be found! Instead kicking players from that server off the network!");
else if (fallback.equals(server))
plugin.getLogger().warning("Maintenance has been enabled on the fallback server! If a player joins on a proxied server, they will be kicked completely instead of being sent to the fallback server!");
server.getPlayers().forEach(p -> {
if (!p.hasPermission("maintenance.bypass") && !settings.getWhitelistedPlayers().containsKey(p.getUniqueId())) {
if (fallback != null && fallback.canAccess(p)) {
p.sendMessage(settings.getMessage("singleMaintenanceActivated").replace("%SERVER%", server.getName()));
p.connect(fallback);
} else
p.disconnect(settings.getMessage("singleMaintenanceKickComplete").replace("%NEWLINE%", "\n").replace("%SERVER%", server.getName()));
} else {
p.sendMessage(settings.getMessage("singleMaintenanceActivated").replace("%SERVER%", server.getName()));
}
});
} else {
if (!settings.getMaintenanceServers().remove(server.getName())) return false;
server.getPlayers().forEach(p -> p.sendMessage(settings.getMessage("singleMaintenanceDeactivated").replace("%SERVER%", server.getName())));
}
/*if (mySQL != null) {
mySQL.executeUpdate(serversQuery, "spigotServers-with-maintenance", maintenanceServers, maintenanceServers);
} else {
spigotServers.set("maintenance-on", maintenanceServers);
saveSpigotServers();
}*/
cancelSingleTask(server);
settings.saveServersToConfig();
return true;
}
@Override
public boolean isServerTaskRunning(final ServerInfo server) {
return serverTaskIds.containsKey(server.getName());
}
@Override
protected int startMaintenanceRunnable(final Runnable runnable) {
return getProxy().getScheduler().schedule(plugin, runnable, 0, 1, TimeUnit.SECONDS).getId();
}
public MaintenanceRunnableBase startSingleMaintenanceRunnable(final ServerInfo server, final int minutes, final boolean enable) {
final MaintenanceRunnableBase runnable = new SingleMaintenanceRunnable(this, (Settings) getSettings(), minutes, enable, server);
serverTaskIds.put(server.getName(), getProxy().getScheduler().schedule(plugin, runnable, 0, 1, TimeUnit.SECONDS).getId());
return runnable;
}
@Override
@@ -88,7 +157,14 @@ public final class MaintenanceBungeePlugin extends MaintenanceModePlugin {
@Override
public void cancelTask() {
getProxy().getScheduler().cancel(taskId);
setTaskId(0);
runnable = null;
taskId = 0;
}
public void cancelSingleTask(final ServerInfo server) {
final Integer task = serverTaskIds.remove(server.getName());
if (task != null)
getProxy().getScheduler().cancel(task);
}
@Override
@@ -114,4 +190,8 @@ public final class MaintenanceBungeePlugin extends MaintenanceModePlugin {
public ProxyServer getProxy() {
return plugin.getProxy();
}
public Logger getLogger() {
return plugin.getLogger();
}
}
@@ -13,23 +13,30 @@ import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.sql.SQLException;
import java.util.List;
import java.util.UUID;
import java.util.*;
public final class SettingsBungee extends Settings {
private final String updateQuery;
private final String maintenanceQuery;
//private final String serversQuery;
private final MySQL mySQL;
private final MaintenanceBungeePlugin maintenancePlugin;
private final MaintenanceBungeeBase plugin;
private final IPingListener pingListener;
private Set<String> maintenanceServers;
private Configuration config;
private Configuration language;
private Configuration whitelist;
private Configuration spigotServers;
private String fallbackServer;
private long millisecondsToCheck;
private long lastMySQLCheck;
SettingsBungee(final MaintenanceBungeeBase plugin) {
SettingsBungee(final MaintenanceBungeePlugin maintenancePlugin, final MaintenanceBungeeBase plugin) {
super(maintenancePlugin);
this.maintenancePlugin = maintenancePlugin;
this.plugin = plugin;
final PluginManager pm = plugin.getProxy().getPluginManager();
@@ -37,7 +44,12 @@ public final class SettingsBungee extends Settings {
pm.registerListener(plugin, listener);
pingListener = listener;
reloadConfigs(createFiles());
if (!plugin.getDataFolder().exists())
plugin.getDataFolder().mkdirs();
createFile("bungee-config.yml");
createFile("WhitelistedPlayers.yml");
createFile("SpigotServers.yml");
reloadConfigs();
final Configuration mySQLSection = config.getSection("mysql");
if (mySQLSection.getBoolean("use-mysql", false)) {
@@ -53,27 +65,73 @@ public final class SettingsBungee extends Settings {
mySQL.executeUpdate("CREATE TABLE IF NOT EXISTS " + mySQLTable + " (setting VARCHAR(16) PRIMARY KEY, value VARCHAR(255))");
updateQuery = "INSERT INTO " + mySQLTable + " (setting, value) VALUES (?, ?) ON DUPLICATE KEY UPDATE value = ?";
maintenanceQuery = "SELECT * FROM " + mySQLTable + " WHERE setting = ?";
//serversQuery = "INSERT INTO " + serversTable + " (setting, value) VALUES (?, ?) ON DUPLICATE KEY UPDATE value = ?";
plugin.getLogger().info("Done!");
} else {
mySQL = null;
updateQuery = null;
maintenanceQuery = null;
//serversQuery = null;
}
}
private void createFile(final String name) {
final File file = new File(plugin.getDataFolder(), name);
if (!file.exists()) {
try (final InputStream in = plugin.getResourceAsStream(name)) {
Files.copy(in, file.toPath());
} catch (final IOException e) {
throw new RuntimeException("Unable to create " + name + " file for MaintenanceBungee", e);
}
}
}
@Override
public void updateExtraConfig() {
public boolean updateExtraConfig() {
// 2.3.1 mysql.update-interval
if (!configContains("mysql.update-interval")) {
setToConfig("mysql.update-interval", 15);
saveConfig();
reloadConfigs();
return true;
}
return false;
}
@Override
public void reloadConfigs() {
reloadConfigs(false);
try {
config = YamlConfiguration.getProvider(YamlConfiguration.class)
.load(new InputStreamReader(new FileInputStream(new File(plugin.getDataFolder(), "bungee-config.yml")), StandardCharsets.UTF_8));
whitelist = YamlConfiguration.getProvider(YamlConfiguration.class).load(new File(plugin.getDataFolder(), "WhitelistedPlayers.yml"));
spigotServers = YamlConfiguration.getProvider(YamlConfiguration.class).load(new File(plugin.getDataFolder(), "spigotServers.yml"));
} catch (final IOException e) {
throw new RuntimeException("Unable to load Maintenance files!", e);
}
loadSettings();
createAndLoadLanguageFile();
}
private void createAndLoadLanguageFile() {
final File file = new File(plugin.getDataFolder(), "language-" + getLanguage() + ".yml");
if (!file.exists()) {
try (final InputStream in = plugin.getResourceAsStream("language-" + getLanguage() + ".yml")) {
Files.copy(in, file.toPath());
} catch (final IOException | NullPointerException e) {
plugin.getLogger().warning("Unable to provide language " + getLanguage());
if (!languageName.equals("en")) {
plugin.getLogger().warning("Falling back to default language: en");
languageName = "en";
createAndLoadLanguageFile();
return;
}
}
}
try {
language = YamlConfiguration.getProvider(YamlConfiguration.class)
.load(new InputStreamReader(new FileInputStream(new File(plugin.getDataFolder(), "language-" + getLanguage() + ".yml")), StandardCharsets.UTF_8));
} catch (final IOException e) {
throw new RuntimeException("Unable to load Maintenance language file!", e);
}
}
@Override
@@ -88,40 +146,38 @@ public final class SettingsBungee extends Settings {
@Override
public void saveWhitelistedPlayers() {
final File file = new File(plugin.getDataFolder(), "WhitelistedPlayers.yml");
try {
YamlConfiguration.getProvider(YamlConfiguration.class).save(whitelist, file);
} catch (final IOException e) {
throw new RuntimeException("Unable to save WhitelistedPlayers.yml!", e);
}
saveFile(whitelist, "WhitelistedPlayers.yml");
}
private void reloadConfigs(final boolean createdNewWhitelist) {
final File file = new File(plugin.getDataFolder(), "bungee-config.yml");
public void saveSpigotServers() {
saveFile(spigotServers, "SpigotServers.yml");
}
private void saveFile(final Configuration config, final String name) {
final File file = new File(plugin.getDataFolder(), name);
try {
config = YamlConfiguration.getProvider(YamlConfiguration.class).load(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8));
whitelist = YamlConfiguration.getProvider(YamlConfiguration.class).load(new File(plugin.getDataFolder(), "WhitelistedPlayers.yml"));
YamlConfiguration.getProvider(YamlConfiguration.class).save(config, file);
} catch (final IOException e) {
throw new RuntimeException("Unable to load bungee-config.yml!", e);
throw new RuntimeException("Unable to save " + name + "!", e);
}
if (createdNewWhitelist) {
whitelist.set("a8179ff3-c201-4a75-bdaa-9d14aca6f83f", "KennyTV");
saveWhitelistedPlayers();
}
loadSettings();
}
@Override
public void loadExtraSettings() {
whitelistedPlayers.clear();
whitelist.getKeys().forEach(key -> whitelistedPlayers.put(UUID.fromString(key), whitelist.getString(key)));
fallbackServer = spigotServers.getString("fallback", "hub");
if (mySQL != null) {
final long configValue = config.getInt("mysql.update-interval");
millisecondsToCheck = configValue > 0 ? configValue * 1000 : -1;
lastMySQLCheck = 0;
}
}/* else {
final List<String> list = spigotServers.getStringList("maintenance-on");
maintenanceServers = list == null ? new HashSet<>() : new HashSet<>(list);
}*/
final List<String> list = spigotServers.getStringList("maintenance-on");
maintenanceServers = list == null ? new HashSet<>() : new HashSet<>(list);
}
@Override
@@ -129,34 +185,6 @@ public final class SettingsBungee extends Settings {
whitelist.set(uuid, s);
}
@Override
public boolean createFiles() {
if (!plugin.getDataFolder().exists())
plugin.getDataFolder().mkdirs();
final File file = new File(plugin.getDataFolder(), "bungee-config.yml");
if (!file.exists()) {
try (final InputStream in = plugin.getResourceAsStream("bungee-config.yml")) {
Files.copy(in, file.toPath());
} catch (final IOException e) {
throw new RuntimeException("Unable to create bungee-config.yml file for MaintenanceBungee", e);
}
}
boolean createdNewWhitelist = false;
final File whitelistFile = new File(plugin.getDataFolder(), "WhitelistedPlayers.yml");
if (!whitelistFile.exists()) {
createdNewWhitelist = true;
try {
whitelistFile.createNewFile();
} catch (final IOException e) {
throw new RuntimeException("Unable to create WhitelistedPlayers.yml file for MaintenanceBungee", e);
}
}
return createdNewWhitelist;
}
@Override
public String getConfigString(final String path) {
final String s = config.getString(path);
@@ -164,6 +192,16 @@ public final class SettingsBungee extends Settings {
plugin.getLogger().warning("The config is missing the following string: " + path);
return "null";
}
return s;
}
@Override
public String getMessage(final String path) {
final String s = language.getString(path);
if (s == null) {
plugin.getLogger().warning("The language file is missing the following string: " + path);
return "null";
}
return ChatColor.translateAlternateColorCodes('&', s);
}
@@ -202,8 +240,14 @@ public final class SettingsBungee extends Settings {
if (mySQL != null && (millisecondsToCheck == -1 || System.currentTimeMillis() - lastMySQLCheck > millisecondsToCheck)) {
mySQL.executeQuery(maintenanceQuery, rs -> {
try {
if (rs.next())
maintenance = Boolean.parseBoolean(rs.getString("value"));
if (rs.next()) {
final boolean databaseValue = Boolean.parseBoolean(rs.getString("value"));
if (databaseValue != maintenance)
maintenancePlugin.serverActions(maintenance);
maintenance = databaseValue;
}
} catch (final SQLException e) {
e.printStackTrace();
}
@@ -211,7 +255,6 @@ public final class SettingsBungee extends Settings {
if (millisecondsToCheck != -1)
lastMySQLCheck = System.currentTimeMillis();
}
return maintenance;
}
@@ -233,4 +276,17 @@ public final class SettingsBungee extends Settings {
public MySQL getMySQL() {
return mySQL;
}
public Set<String> getMaintenanceServers() {
return maintenanceServers;
}
public void saveServersToConfig() {
spigotServers.set("maintenance-on", new ArrayList<>(maintenanceServers));
saveSpigotServers();
}
public String getFallbackServer() {
return fallbackServer;
}
}
@@ -4,54 +4,59 @@ import eu.kennytv.maintenance.bungee.MaintenanceBungeePlugin;
import eu.kennytv.maintenance.bungee.SettingsBungee;
import eu.kennytv.maintenance.bungee.util.ProxiedSenderInfo;
import eu.kennytv.maintenance.core.command.MaintenanceCommand;
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnableBase;
import eu.kennytv.maintenance.core.util.SenderInfo;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
public final class MaintenanceBungeeCommand extends MaintenanceCommand {
private final MaintenanceBungeePlugin plugin;
private final SettingsBungee settingsBungee;
public MaintenanceBungeeCommand(final MaintenanceBungeePlugin plugin, final SettingsBungee settings) {
super(plugin, settings, "MaintenanceBungee");
this.plugin = plugin;
settingsBungee = settings;
}
@Override
protected void addPlayerToWhitelist(final SenderInfo sender, final String name) {
final ProxiedPlayer selected = ProxyServer.getInstance().getPlayer(name);
final ProxiedPlayer selected = plugin.getProxy().getPlayer(name);
if (selected == null) {
sender.sendMessage(plugin.getPrefix() + "§cThere's no player online with that name.");
sender.sendMessage(settings.getMessage("playerNotOnline"));
return;
}
if (settings.addWhitelistedPlayer(selected.getUniqueId(), selected.getName()))
sender.sendMessage(plugin.getPrefix() + "§aAdded §b" + selected.getName() + " §ato the maintenance whitelist!");
sender.sendMessage(settings.getMessage("whitelistAdded").replace("%PLAYER%", selected.getName()));
else
sender.sendMessage(plugin.getPrefix() + "§b" + selected.getName() + " §calready is in the maintenance whitelist!");
sender.sendMessage(settings.getMessage("whitelistAlreadyAdded").replace("%PLAYER%", selected.getName()));
}
@Override
protected void removePlayerFromWhitelist(final SenderInfo sender, final String name) {
final ProxiedPlayer selected = ProxyServer.getInstance().getPlayer(name);
final ProxiedPlayer selected = plugin.getProxy().getPlayer(name);
if (selected == null) {
if (settings.removeWhitelistedPlayer(name.toLowerCase()))
sender.sendMessage(plugin.getPrefix() + "§aRemoved §b" + name.toLowerCase() + " §afrom the maintenance whitelist!");
if (settings.removeWhitelistedPlayer(name))
sender.sendMessage(settings.getMessage("whitelistRemoved").replace("%PLAYER%", name));
else
sender.sendMessage(plugin.getPrefix() + "§cThere is no player with that name in the maintenance whitelist!");
sender.sendMessage(settings.getMessage("whitelistNotFound"));
return;
}
if (settings.removeWhitelistedPlayer(selected.getUniqueId()))
sender.sendMessage(plugin.getPrefix() + "§aRemoved §b" + selected.getName() + " §afrom the maintenance whitelist!");
sender.sendMessage(settings.getMessage("whitelistRemoved").replace("%PLAYER%", selected.getName()));
else
sender.sendMessage(plugin.getPrefix() + "§cThis player is not in the maintenance whitelist!");
sender.sendMessage(settings.getMessage("whitelistNotFound"));
}
@Override
protected void checkForUpdate(final SenderInfo sender) {
if (plugin.updateAvailable()) {
sender.sendMessage(plugin.getPrefix() + "§cNewest version available: §aVersion " + plugin.getNewestVersion() + "§c, you're still on §a" + plugin.getVersion());
sender.sendMessage(plugin.getPrefix() + "§cNewest version available: §aVersion " + plugin.getNewestVersion() + "§c, you're on §a" + plugin.getVersion());
sender.sendMessage(plugin.getPrefix() + "§c§lWARNING: §cYou will have to restart the proxy to prevent further issues and to complete the update!" +
" If you can't do that, don't update!");
final TextComponent tc = new TextComponent("§6× §8[§aUpdate§8]");
@@ -63,4 +68,94 @@ public final class MaintenanceBungeeCommand extends MaintenanceCommand {
} else
sender.sendMessage(plugin.getPrefix() + "§aYou already have the latest version of the plugin!");
}
@Override
protected void handleToggleServerCommand(final SenderInfo sender, final String args[]) {
final ServerInfo server = plugin.getProxy().getServerInfo(args[1]);
if (server == null) {
sender.sendMessage(settings.getMessage("serverNotFound"));
return;
}
final boolean maintenance = args[0].equalsIgnoreCase("on");
if (maintenance == settingsBungee.getMaintenanceServers().contains(server.getName())) {
sender.sendMessage(settings.getMessage(maintenance ? "alreadyEnabled" : "alreadyDisabled"));
return;
}
if (!plugin.setMaintenanceToServer(server, maintenance))
sender.sendMessage(settings.getMessage(maintenance ? "singleServerAlreadyEnabled" : "singleServerAlreadyDisabled"));
else if (!plugin.getProxy().getPlayer(sender.getUuid()).getServer().getInfo().equals(server))
sender.sendMessage(settings.getMessage(maintenance ? "singleMaintenanceActivated" : "singleMaintenanceDeactivated").replace("%SERVER%", server.getName()));
}
@Override
protected void handleTimerServerCommands(final SenderInfo sender, final String args[]) {
if (args[0].equalsIgnoreCase("endtimer")) {
if (checkPermission(sender, "servertimer")) return;
if (checkTimerArgs(sender, args[2], "singleEndtimerUsage")) return;
final ServerInfo server = checkSingleTimerArgs(sender, args);
if (server == null) return;
if (!plugin.isMaintenance(server)) {
sender.sendMessage(settings.getMessage("singleServerAlreadyDisabled").replace("%SERVER%", server.getName()));
return;
}
final MaintenanceRunnableBase runnable = plugin.startSingleMaintenanceRunnable(server, Integer.parseInt(args[2]), false);
sender.sendMessage(settings.getMessage("endtimerStarted").replace("%TIME%", runnable.getTime()));
} else if (args[0].equalsIgnoreCase("starttimer")) {
if (checkPermission(sender, "servertimer")) return;
if (checkTimerArgs(sender, args[2], "singleStarttimerUsage")) return;
final ServerInfo server = checkSingleTimerArgs(sender, args);
if (server == null) return;
if (plugin.isMaintenance(server)) {
sender.sendMessage(settings.getMessage("singleServerAlreadyEnabled").replace("%SERVER%", server.getName()));
return;
}
final MaintenanceRunnableBase runnable = plugin.startSingleMaintenanceRunnable(server, Integer.parseInt(args[2]), true);
sender.sendMessage(settings.getMessage("starttimerStarted").replace("%TIME%", runnable.getTime()));
} else if (args[0].equalsIgnoreCase("timer")) {
if (args[1].equalsIgnoreCase("abort") || args[1].equalsIgnoreCase("stop") || args[1].equalsIgnoreCase("cancel")) {
if (checkPermission(sender, "servertimer")) return;
final ServerInfo server = plugin.getProxy().getServerInfo(args[2]);
if (server == null) {
sender.sendMessage(settings.getMessage("serverNotFound"));
return;
}
if (!plugin.isServerTaskRunning(server)) {
sender.sendMessage(settings.getMessage("timerNotRunning"));
return;
}
plugin.cancelSingleTask(server);
sender.sendMessage(settings.getMessage("timerCancelled"));
} else
sendUsage(sender);
}
}
@Override
protected void showMaintenanceStatus(final SenderInfo sender) {
if (settingsBungee.getMaintenanceServers().isEmpty()) {
sender.sendMessage(settings.getMessage("singleServerMaintenanceListEmpty"));
} else {
sender.sendMessage(settings.getMessage("singleServerMaintenanceList"));
settingsBungee.getMaintenanceServers().forEach(server -> sender.sendMessage("§8- §b" + server));
}
}
private ServerInfo checkSingleTimerArgs(final SenderInfo sender, final String[] args) {
final ServerInfo server = plugin.getProxy().getServerInfo(args[1]);
if (server == null) {
sender.sendMessage(settings.getMessage("serverNotFound"));
return null;
}
if (plugin.isServerTaskRunning(server)) {
sender.sendMessage(settings.getMessage("timerAlreadyRunning"));
return null;
}
return server;
}
}
@@ -12,9 +12,14 @@ import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
import net.md_5.bungee.event.EventPriority;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
public final class PostLoginListener implements Listener {
private final MaintenanceBungeePlugin plugin;
private final SettingsBungee settings;
private final Set<UUID> notifiedPlayers = new HashSet<>();
public PostLoginListener(final MaintenanceBungeePlugin plugin, final SettingsBungee settings) {
this.plugin = plugin;
@@ -32,16 +37,17 @@ public final class PostLoginListener implements Listener {
if (settings.isJoinNotifications())
plugin.getProxy().getPlayers().stream().filter(player -> player.hasPermission("maintenance.joinnotification"))
.forEach(player -> player.sendMessage(settings.getJoinNotification().replace("%PLAYER%", p.getName())));
.forEach(player -> player.sendMessage(settings.getMessage("joinNotification").replace("%PLAYER%", p.getName())));
return;
}
}
if (!p.hasPermission("maintenance.admin")) return;
if (!p.hasPermission("maintenance.admin") || notifiedPlayers.contains(p.getUniqueId())) return;
plugin.async(() -> {
if (plugin.updateAvailable()) {
p.sendMessage(plugin.getPrefix() + "§cThere is a newer version available: §aVersion " + plugin.getNewestVersion() + "§c, you're still on §a" + plugin.getVersion());
p.sendMessage(plugin.getPrefix() + "§cThere is a newer version available: §aVersion " + plugin.getNewestVersion() + "§c, you're on §a" + plugin.getVersion());
notifiedPlayers.add(p.getUniqueId());
final TextComponent tc1 = new TextComponent(TextComponent.fromLegacyText(plugin.getPrefix() + " "));
final TextComponent tc2 = new TextComponent(TextComponent.fromLegacyText("§cDownload it at: §6https://www.spigotmc.org/resources/maintenancemode.40699/"));
@@ -29,8 +29,13 @@ public final class ProxyPingListener implements Listener, IPingListener {
if (!settings.isMaintenance()) return;
final ServerPing ping = event.getResponse();
ping.getVersion().setProtocol(1);
ping.getVersion().setName(settings.getPlayerCountMessage());
if (settings.hasCustomPlayerCountMessage()) {
ping.getVersion().setProtocol(1);
ping.getVersion().setName(settings.getPlayerCountMessage()
.replace("%ONLINE%", Integer.toString(ping.getPlayers().getOnline()))
.replace("%MAX%", Integer.toString(ping.getPlayers().getMax())));
}
ping.setDescription(settings.getRandomPingMessage());
ping.getPlayers().setOnline(0);
ping.getPlayers().setMax(0);
@@ -0,0 +1,53 @@
package eu.kennytv.maintenance.bungee.listener;
import eu.kennytv.maintenance.bungee.MaintenanceBungeePlugin;
import eu.kennytv.maintenance.bungee.SettingsBungee;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.ServerConnectEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
import net.md_5.bungee.event.EventPriority;
public final class ServerConnectListener implements Listener {
private final MaintenanceBungeePlugin plugin;
private final SettingsBungee settings;
private boolean warned;
public ServerConnectListener(final MaintenanceBungeePlugin plugin, final SettingsBungee settings) {
this.plugin = plugin;
this.settings = settings;
}
@EventHandler(priority = EventPriority.HIGHEST)
public void serverConnect(final ServerConnectEvent event) {
final ProxiedPlayer p = event.getPlayer();
final ServerInfo target = event.getTarget();
if (!settings.getMaintenanceServers().contains(target.getName())) return;
if (p.hasPermission("maintenance.bypass") || settings.getWhitelistedPlayers().containsKey(p.getUniqueId()))
return;
event.setCancelled(true);
if (settings.isJoinNotifications()) {
target.getPlayers().stream().filter(player -> player.hasPermission("maintenance.joinnotification"))
.forEach(player -> player.sendMessage(settings.getMessage("joinNotification").replace("%PLAYER%", p.getName())));
}
// Normal serverconnect
if (event.getReason() != ServerConnectEvent.Reason.JOIN_PROXY && event.getReason() != ServerConnectEvent.Reason.KICK_REDIRECT
&& event.getReason() != ServerConnectEvent.Reason.LOBBY_FALLBACK && event.getReason() != ServerConnectEvent.Reason.SERVER_DOWN_REDIRECT) {
p.sendMessage(settings.getMessage("singleMaintenanceKick").replace("%SERVER%", target.getName()));
return;
}
// If it's the initial proxy join or a kick from another server, go back to fallback server
final ServerInfo fallback = plugin.getProxy().getServerInfo(settings.getFallbackServer());
if (fallback == null || !fallback.canAccess(p) || plugin.isMaintenance(fallback)) {
p.disconnect(settings.getMessage("singleMaintenanceKickComplete").replace("%NEWLINE%", "\n").replace("%SERVER%", target.getName()));
if (!warned) {
plugin.getLogger().warning("Could not send player to the fallback server set in the SpigotServers.yml! Instead kicking player off the network!");
warned = true;
}
} else
p.connect(fallback);
}
}
@@ -12,6 +12,7 @@ import javax.net.ssl.HttpsURLConnection;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.*;
import java.util.concurrent.TimeUnit;
@@ -266,7 +267,7 @@ public final class MetricsLite {
}
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
final GZIPOutputStream gzip = new GZIPOutputStream(outputStream);
gzip.write(str.getBytes("UTF-8"));
gzip.write(str.getBytes(StandardCharsets.UTF_8));
gzip.close();
return outputStream.toByteArray();
}
@@ -0,0 +1,33 @@
package eu.kennytv.maintenance.bungee.runnable;
import eu.kennytv.maintenance.bungee.MaintenanceBungeePlugin;
import eu.kennytv.maintenance.core.MaintenanceModePlugin;
import eu.kennytv.maintenance.core.Settings;
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnableBase;
import net.md_5.bungee.api.config.ServerInfo;
public final class SingleMaintenanceRunnable extends MaintenanceRunnableBase {
private final ServerInfo server;
public SingleMaintenanceRunnable(final MaintenanceModePlugin plugin, final Settings settings, final int minutes,
final boolean enable, final ServerInfo server) {
super(plugin, settings, minutes, enable);
this.server = server;
}
@Override
protected void finish() {
final MaintenanceBungeePlugin plugin = (MaintenanceBungeePlugin) this.plugin;
plugin.setMaintenanceToServer(server, enable);
}
@Override
protected String startMessageKey() {
return settings.getMessage("singleStarttimerBroadcast").replace("%TIME%", getTime()).replace("%SERVER%", server.getName());
}
@Override
protected String endMessageKey() {
return settings.getMessage("singleEndtimerBroadcast").replace("%TIME%", getTime()).replace("%SERVER%", server.getName());
}
}
@@ -7,7 +7,7 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.UUID;
public final class ProxiedSenderInfo extends SenderInfo {
public final class ProxiedSenderInfo implements SenderInfo {
private final CommandSender sender;
public ProxiedSenderInfo(final CommandSender sender) {
@@ -0,0 +1,6 @@
# Enables maintenance on certain Spigot servers managed by your Bungee instance(s)
# If it's enabled on a server with players on it, they will be forwarded to the fallback server (or kicked completely if not set correctly)
maintenance-on:
#- SpigotServer1
#- AnotherServer
fallback: hub
@@ -1,5 +1,4 @@
# MaintenanceBungee Plugin by KennyTV
# Version ${project.version}
# Enables maintenance-mode.
enable-maintenance-mode: false
@@ -10,36 +9,34 @@ pingmessages:
- "&cMaintenance mode!%NEWLINE%&6We will be back soon!"
#- "Another entry"
# Is shown at the top right corner of the server in the serverlist,
# If set to true, the message below will be shown at the top right corner of the server in the serverlist,
# where the playercount would normally be displayed.
# If set to false, the normal playercount will be shown.
# Alternatively you can use '%ONLINE%' and '%MAX% if you want to include the playercount in a custom message (e.g. '&cMaintenance &7%ONLINE%&8/&7%MAX%').
enable-playercountmessage: true
playercountmessage: "&4Maintenance"
# Is shown when you move your mouse above the text at the top right corner of the server in the serverlist,
# where the playercount would normally be displayed.
playercounthovermessage: "&cCurrently under%NEWLINE%&cmaintenance"
# Will be shown, when a player tries to join on the server without the permission.
# Is shown when a player tries to join while maintenance is enabled and they don't have the permission to bypass it.
kickmessage: "&cThe server is currently under maintenance!%NEWLINE%Try again later!"
# Some self explanatory messages
no-permission: "&cYou do not have the permission to execute that command."
maintenance-activated: "&6Maintenance mode is now activated."
maintenance-deactivated: "&6Maintenance mode is now deactivated."
starttimer-broadcast-mesage: '&8[&eMaintenance&8] &7Maintenance mode will be enabled in &6%MINUTES% minutes&7.'
endtimer-broadcast-mesage: '&8[&eMaintenance&8] &7Maintenance mode will be disabled in &6%MINUTES% minutes&7.'
# If using the timer command: In what intervalls before enabling/disabling maintenance there will be a broadcast.
timer-broadcasts-for-minutes: [60, 30, 15, 10, 5, 4, 3, 2, 1]
timer-broadcast-for-seconds: [1200, 900, 600, 300, 120, 60, 30, 20, 10, 5, 4, 3, 2, 1]
# If set to true, players with the maintenance.joinnotification permission will receive a message,
# that a player tried to join the server while maintenance is enabled.
send-join-notification: false
join-notification: "&e%PLAYER% &ctried to join the server."
# If set to true, the server icon will be changed to maintenance-icon.png in the Bungee main/base-folder.
custom-maintenance-icon: false
# Changes the language of command feedback/messages.
# Currently available are: en (English), de (German)
language: en
# Only enable MySQL if you really know what you are doing.
mysql:
use-mysql: false
@@ -52,5 +49,5 @@ mysql:
table: maintenance_settings
# Requests to the database will only be made at least x seconds after the last request,
# so there won't be a request on every single ping on a server with many players.
# Set to 0 to make a database request on every single ping.
# Set this to 0 to make a database request on every single ping.
update-interval: 15
+1 -1
View File
@@ -6,7 +6,7 @@
<parent>
<artifactId>maintenance-base</artifactId>
<groupId>eu.kennytv</groupId>
<version>2.3.1</version>
<version>2.5</version>
</parent>
<artifactId>maintenance-core</artifactId>
@@ -2,6 +2,9 @@ package eu.kennytv.maintenance.core;
import eu.kennytv.maintenance.api.IMaintenance;
import eu.kennytv.maintenance.core.hook.ServerListPlusHook;
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnable;
import eu.kennytv.maintenance.core.util.ServerType;
import eu.kennytv.maintenance.core.util.Version;
import java.io.*;
import java.net.HttpURLConnection;
@@ -10,15 +13,19 @@ import java.net.URL;
import java.net.URLConnection;
public abstract class MaintenanceModePlugin implements IMaintenance {
protected final String version;
protected int taskId;
protected final Version version;
protected ServerListPlusHook serverListPlusHook;
protected MaintenanceRunnable runnable;
protected int taskId;
private final String prefix;
private String newestVersion;
private final ServerType serverType;
private Version newestVersion;
protected MaintenanceModePlugin(final String prefix, final String version) {
protected MaintenanceModePlugin(final String prefix, final String version, final ServerType serverType) {
this.prefix = prefix;
this.version = version;
this.version = new Version(version);
this.serverType = serverType;
checkNewestVersion();
}
@Override
@@ -28,23 +35,24 @@ public abstract class MaintenanceModePlugin implements IMaintenance {
@Override
public String getVersion() {
return version;
return version.toString();
}
@Override
public boolean isTaskRunning() {
return taskId != 0;
return taskId != 0 && runnable != null;
}
public void setTaskId(final int taskId) {
this.taskId = taskId;
public void startMaintenanceRunnable(final int minutes, final boolean enable) {
runnable = new MaintenanceRunnable(this, (Settings) getSettings(), minutes, enable);
taskId = startMaintenanceRunnable(runnable);
}
public String getNewestVersion() {
public Version getNewestVersion() {
return newestVersion;
}
public abstract int schedule(Runnable runnable);
protected abstract int startMaintenanceRunnable(Runnable runnable);
public abstract void async(Runnable runnable);
@@ -54,25 +62,57 @@ public abstract class MaintenanceModePlugin implements IMaintenance {
public abstract void broadcast(String message);
public MaintenanceRunnable getRunnable() {
return runnable;
}
public String getPrefix() {
return prefix;
}
public boolean updateAvailable() {
public ServerType getServerType() {
return serverType;
}
public String formatedTimer() {
if (!isTaskRunning()) return "-";
final int preHours = runnable.getSecondsLeft() / 60;
final int minutes = preHours % 60;
final int seconds = runnable.getSecondsLeft() % 60;
return String.format("%02d:%02d:%02d", preHours / 60, minutes, seconds);
}
public void checkNewestVersion() {
try {
final HttpURLConnection c = (HttpURLConnection) new URL("https://api.spigotmc.org/legacy/update.php?resource=40699").openConnection();
final String newVersion = new BufferedReader(new InputStreamReader(c.getInputStream())).readLine().replaceAll("[a-zA-Z -]", "");
final String newVersionString = new BufferedReader(new InputStreamReader(c.getInputStream())).readLine();
final Version newVersion = new Version(newVersionString);
final boolean available = !newVersion.equals(version);
if (available)
newestVersion = newVersion;
return available;
} catch (final Exception ignored) {
return false;
}
}
public boolean updateAvailable() {
checkNewestVersion();
return version.compareTo(newestVersion) == -1;
}
public String getUpdateMessage() {
if (version.compareTo(newestVersion) == -1) {
return "§cNewest version available: §aVersion " + newestVersion + "§c, you're on §a" + version;
} else if (version.compareTo(newestVersion) != 0) {
if (version.getTag().equalsIgnoreCase("snapshot")) {
return "§cYou're running a development version, please report bugs on the Discord server (https://kennytv.eu/discord) or the GitHub tracker (https://kennytv.eu/maintenance/issues)";
} else {
return "§cYou're running a version, that doesn't exist! §cN§ai§dc§ee§5!";
}
}
return "You have the latest version of the plugin installed.";
}
public boolean installUpdate() {
try {
URL url = null;
@@ -7,38 +7,35 @@ import java.util.*;
public abstract class Settings implements ISettings {
private static final Random RANDOM = new Random();
protected final Map<UUID, String> whitelistedPlayers = new HashMap<>();
private final MaintenanceModePlugin plugin;
protected boolean maintenance;
private Set<Integer> broadcastIntervalls;
private List<String> pingMessages;
private String timerBroadcastMessage;
private String endtimerBroadcastMessage;
private String kickMessage;
private String joinNotification;
private String noPermMessage;
private String maintenanceActivated;
private String maintenanceDeactivated;
private String playerCountMessage;
private String playerCountHoverMessage;
private boolean joinNotifications;
private String kickMessage;
protected String languageName;
private boolean customPlayerCountMessage;
private boolean customMaintenanceIcon;
private boolean joinNotifications;
protected Settings(final MaintenanceModePlugin plugin) {
this.plugin = plugin;
}
protected void loadSettings() {
updateConfig();
pingMessages = getConfigList("pingmessages");
timerBroadcastMessage = getConfigString("starttimer-broadcast-mesage");
endtimerBroadcastMessage = getConfigString("endtimer-broadcast-mesage");
kickMessage = getConfigString("kickmessage");
joinNotification = getConfigString("join-notification");
noPermMessage = getConfigString("no-permission");
maintenanceActivated = getConfigString("maintenance-activated");
maintenanceDeactivated = getConfigString("maintenance-deactivated");
maintenance = getConfigBoolean("enable-maintenance-mode");
joinNotifications = getConfigBoolean("send-join-notification");
customPlayerCountMessage = getConfigBoolean("enable-playercountmessage");
customMaintenanceIcon = getConfigBoolean("custom-maintenance-icon");
broadcastIntervalls = new HashSet<>(getConfigIntList("timer-broadcasts-for-minutes"));
playerCountMessage = getConfigString("playercountmessage");
playerCountHoverMessage = getConfigString("playercounthovermessage");
joinNotifications = getConfigBoolean("send-join-notification");
broadcastIntervalls = new HashSet<>(getConfigIntList("timer-broadcast-for-seconds"));
playerCountMessage = getColoredString(getConfigString("playercountmessage"));
playerCountHoverMessage = getColoredString(getConfigString("playercounthovermessage"));
kickMessage = getColoredString(getConfigString("kickmessage"));
languageName = getConfigString("language").toLowerCase();
if (customMaintenanceIcon)
reloadMaintenanceIcon();
@@ -46,28 +43,48 @@ public abstract class Settings implements ISettings {
}
private void updateConfig() {
boolean fileChanged = false;
// 2.3 pingmessage -> pingmessages
if (configContains("pingmessage")) {
final List<Object> list = new ArrayList<>();
final List<String> list = new ArrayList<>();
list.add(getConfigString("pingmessage"));
setToConfig("pingmessages", list);
setToConfig("pingmessage", null);
fileChanged = true;
}
// 2.4 enable-playercountmessage
if (!configContains("enable-playercountmessage")) {
setToConfig("enable-playercountmessage", true);
fileChanged = true;
}
// 2.4. timer-broadcasts-for-minutes -> timer-broadcast-for-seconds
if (configContains("timer-broadcasts-for-minutes") || !configContains("timer-broadcast-for-seconds")) {
setToConfig("timer-broadcast-for-seconds", Arrays.asList(1200, 900, 600, 300, 120, 60, 30, 20, 10, 5, 4, 3, 2, 1));
setToConfig("timer-broadcasts-for-minutes", null);
fileChanged = true;
}
// 2.5 language
if (!configContains("language")) {
setToConfig("language", "en");
}
if (updateExtraConfig() || fileChanged) {
saveConfig();
reloadConfigs();
}
updateExtraConfig();
}
public void updateExtraConfig() {
public boolean updateExtraConfig() {
return false;
}
public abstract void saveWhitelistedPlayers();
public abstract boolean createFiles();
public abstract String getConfigString(String path);
public abstract String getMessage(String path);
public abstract boolean getConfigBoolean(String path);
public abstract List<Integer> getConfigIntList(String path);
@@ -96,34 +113,6 @@ public abstract class Settings implements ISettings {
return broadcastIntervalls;
}
public String getTimerBroadcastMessage() {
return timerBroadcastMessage;
}
public String getEndtimerBroadcastMessage() {
return endtimerBroadcastMessage;
}
public String getKickMessage() {
return kickMessage;
}
public String getJoinNotification() {
return joinNotification;
}
public String getNoPermMessage() {
return noPermMessage;
}
public String getMaintenanceActivated() {
return maintenanceActivated;
}
public String getMaintenanceDeactivated() {
return maintenanceDeactivated;
}
public String getPlayerCountMessage() {
return playerCountMessage;
}
@@ -132,6 +121,14 @@ public abstract class Settings implements ISettings {
return playerCountHoverMessage;
}
public String getKickMessage() {
return kickMessage;
}
public String getLanguage() {
return languageName;
}
public void setMaintenance(final boolean maintenance) {
this.maintenance = maintenance;
}
@@ -139,7 +136,11 @@ public abstract class Settings implements ISettings {
public String getRandomPingMessage() {
if (pingMessages.isEmpty()) return "";
final String s = pingMessages.size() > 1 ? pingMessages.get(RANDOM.nextInt(pingMessages.size())) : pingMessages.get(0);
return getColoredString(s.replace("%NEWLINE%", "\n"));
return getColoredString(s.replace("%NEWLINE%", "\n").replace("%TIMER%", plugin.formatedTimer()));
}
public boolean hasCustomPlayerCountMessage() {
return customPlayerCountMessage;
}
@Override
@@ -174,8 +175,10 @@ public abstract class Settings implements ISettings {
@Deprecated
@Override
public boolean removeWhitelistedPlayer(final String name) {
if (!whitelistedPlayers.containsValue(name)) return false;
final UUID uuid = whitelistedPlayers.entrySet().stream().filter(entry -> entry.getValue().equals(name)).findAny().get().getKey();
final Map.Entry<UUID, String> entry = whitelistedPlayers.entrySet().stream().filter(e -> e.getValue().equalsIgnoreCase(name)).findAny().orElse(null);
if (entry == null) return false;
final UUID uuid = entry.getKey();
whitelistedPlayers.remove(uuid);
setWhitelist(uuid.toString(), null);
saveWhitelistedPlayers();
@@ -0,0 +1,21 @@
package eu.kennytv.maintenance.core.command;
import eu.kennytv.maintenance.core.util.SenderInfo;
final class CommandInfo {
private final String[] messages;
private final String permission;
CommandInfo(final String permission, final String... messages) {
this.messages = messages;
this.permission = permission;
}
public boolean hasPermission(final SenderInfo sender) {
return sender.hasPermission("maintenance." + permission);
}
public String[] getMessages() {
return messages;
}
}
@@ -2,63 +2,91 @@ package eu.kennytv.maintenance.core.command;
import eu.kennytv.maintenance.core.MaintenanceModePlugin;
import eu.kennytv.maintenance.core.Settings;
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnable;
import eu.kennytv.maintenance.core.util.SenderInfo;
import eu.kennytv.maintenance.core.util.ServerType;
import java.util.Arrays;
import java.util.Map;
import java.util.UUID;
import java.util.*;
public abstract class MaintenanceCommand {
protected final MaintenanceModePlugin plugin;
protected final Settings settings;
private final List<CommandInfo> commandInfos;
private final String name;
protected MaintenanceCommand(final MaintenanceModePlugin plugin, final Settings settings, final String name) {
this.plugin = plugin;
this.settings = settings;
this.name = name;
this.commandInfos = new ArrayList<>();
addCommandInfo("reload", "§6/maintenance reload §7(Reloads the config file, whitelist file and the server-icon)");
addCommandInfo("toggle", "§6/maintenance on §7(Enables maintenance mode)", "§6/maintenance off §7(Disables maintenance mode)");
if (plugin.getServerType() == ServerType.BUNGEE) {
addCommandInfo("toggleserver", "§6/maintenance on <server> §7(Enables maintenance mode on a specific proxied server)",
"§6/maintenance off <server> §7(Disables maintenance mode on a specific proxied server)");
}
addCommandInfo("timer", "§6/maintenance starttimer <minutes> §7(After the given time in minutes, maintenance mode will be enabled)",
"§6/maintenance endtimer <minutes> §7(After the given time in minutes, maintenance mode will be disabled)",
"§6/maintenance timer abort §7(If running, the current timer will be aborted)");
if (plugin.getServerType() == ServerType.BUNGEE) {
addCommandInfo("servertimer", "§6/maintenance starttimer <server> <minutes> §7(After the given time in minutes, maintenance mode will be enabled on the given server)",
"§6/maintenance endtimer <server> <minutes> §7(After the given time in minutes, maintenance mode will be disabled on the given server)",
"§6/maintenance timer abort <server> §7(If running, the timer running for that server will be aborted)");
}
addCommandInfo("whitelist.list", "§6/maintenance whitelist §7(Shows all whitelisted players for the maintenance mode)");
addCommandInfo("whitelist.add", "§6/maintenance add <player> §7(Adds the player to the maintenance whitelist, so they can join the server even though maintenance is enabled)");
addCommandInfo("whitelist.remove", "§6/maintenance remove <player> §7(Removes the player from the maintenance whitelist)");
addCommandInfo("setmotd", "§6/maintenance setmotd <index> <1/2> <message> §7(Sets a motd for maintenance mode)", "§6/maintenance removemotd <index> §7(Removes a maintenance motd)");
addCommandInfo("motd", "§6/maintenance motd §7(Lists the currently set maintenance motds)");
addCommandInfo("update", "§6/maintenance update §7(Remotely downloads the newest version of the plugin onto your server)");
}
private void addCommandInfo(final String permission, final String... messages) {
commandInfos.add(new CommandInfo(permission, messages));
}
public void execute(final SenderInfo sender, final String[] args) {
if (checkPermission(sender, "command")) return;
if (args.length == 1) {
if (args[0].equalsIgnoreCase("on")) {
if (args[0].equalsIgnoreCase("on") || args[0].equalsIgnoreCase("off")) {
if (checkPermission(sender, "toggle")) return;
plugin.setMaintenance(true);
} else if (args[0].equalsIgnoreCase("off")) {
if (checkPermission(sender, "toggle")) return;
plugin.setMaintenance(false);
final boolean maintenance = args[0].equalsIgnoreCase("on");
if (maintenance == plugin.isMaintenance()) {
sender.sendMessage(settings.getMessage(maintenance ? "alreadyEnabled" : "alreadyDisabled"));
return;
}
plugin.setMaintenance(maintenance);
} else if (args[0].equalsIgnoreCase("reload")) {
if (checkPermission(sender, "reload")) return;
settings.reloadConfigs();
sender.sendMessage(plugin.getPrefix() + "§aReloaded config, whitelistedplayers and the maintenance icon");
sender.sendMessage(settings.getMessage("reload"));
} else if (args[0].equalsIgnoreCase("update")) {
if (checkPermission(sender, "update")) return;
checkForUpdate(sender);
} else if (args[0].equals("forceupdate")) {
if (checkPermission(sender, "update")) return;
sender.sendMessage(plugin.getPrefix() + "§c§lDownloading update...");
sender.sendMessage(settings.getMessage("updateDownloading"));
if (plugin.installUpdate())
sender.sendMessage(plugin.getPrefix() + "§a§lThe update was successful! To prevent issues with tasks and to complete the update, you have to restart the proxy!");
sender.sendMessage(settings.getMessage("updateFinished"));
else
sender.sendMessage(plugin.getPrefix() + "§4Failed!");
sender.sendMessage(settings.getMessage("updateFailed"));
} else if (args[0].equalsIgnoreCase("whitelist")) {
if (checkPermission(sender, "whitelist.list")) return;
final Map<UUID, String> players = settings.getWhitelistedPlayers();
if (players.isEmpty()) {
sender.sendMessage(plugin.getPrefix() + "§cThe maintenance whitelist is empty! Use \"/maintenance add <player>\" to add someone!");
sender.sendMessage(settings.getMessage("whitelistEmtpy"));
} else if (players.size() == 1 && players.containsKey(UUID.fromString("a8179ff3-c201-4a75-bdaa-9d14aca6f83f"))) {
sender.sendMessage(plugin.getPrefix() + "§cUse \"/maintenance add <player>\" to add someone. Alternatively, you can add the uuid of a player to the WhitelistedPlayers.yml as seen in the example in the file!");
sender.sendMessage(settings.getMessage("whitelistEmptyDefault"));
} else {
sender.sendMessage("§6Whitelisted players for maintenance:");
players.forEach((key, value) -> sender.sendMessage("§8- §e" + value + " §8(§7" + key + "§8)"));
sender.sendMessage(settings.getMessage("whitelistedPlayers"));
final String format = settings.getMessage("whitelistedPlayersFormat");
players.forEach((key, value) -> sender.sendMessage(format.replace("%NAME%", value).replace("%UUID%", key.toString())));
sender.sendMessage("");
}
} else if (args[0].equalsIgnoreCase("motd")) {
if (checkPermission(sender, "motd")) return;
sender.sendMessage(plugin.getPrefix() + "§7List of your maintenance motds:");
sender.sendMessage(settings.getMessage("motdList"));
for (int i = 0; i < settings.getPingMessages().size(); i++) {
sender.sendMessage("§b" + (i + 1) + "§8§m---------");
for (final String motd : settings.getColoredString(settings.getPingMessages().get(i)).split("%NEWLINE%")) {
@@ -66,66 +94,50 @@ public abstract class MaintenanceCommand {
}
}
sender.sendMessage("§8§m----------");
} else if (args[0].equalsIgnoreCase("status") && plugin.getServerType() == ServerType.BUNGEE) {
if (checkPermission(sender, "status")) return;
showMaintenanceStatus(sender);
} else
sendUsage(sender);
} else if (args.length == 2) {
if (args[0].equalsIgnoreCase("endtimer")) {
if (checkPermission(sender, "timer")) return;
if (args[0].equalsIgnoreCase("help")) {
if (!isNumeric(args[1])) {
sender.sendMessage(plugin.getPrefix() + "§6/maintenance endtimer <minutes>");
sender.sendMessage(settings.getMessage("helpUsage"));
return;
}
if (plugin.isTaskRunning()) {
sender.sendMessage(plugin.getPrefix() + "§cThere's already a starttimer scheduled!");
sendUsage(sender, Integer.parseInt(args[1]));
} else if ((args[0].equalsIgnoreCase("on") || args[0].equalsIgnoreCase("off")) && plugin.getServerType() == ServerType.BUNGEE) {
if (checkPermission(sender, "toggleserver")) return;
handleToggleServerCommand(sender, args);
} else if (args[0].equalsIgnoreCase("endtimer")) {
if (checkPermission(sender, "timer")) return;
if (checkTimerArgs(sender, args[1], "endtimerUsage")) return;
if (!plugin.isMaintenance()) {
sender.sendMessage(settings.getMessage("alreadyDisabled"));
return;
}
final int minutes = Integer.parseInt(args[1]);
if (minutes > 40320) {
sender.sendMessage(plugin.getPrefix() + "§cThe number has to be less than 40320 (28 days)!");
return;
}
if (minutes < 1) {
sender.sendMessage(plugin.getPrefix() + "§cThink about running a timer for a negative amount of minutes. Doesn't work §othat §r§cwell.");
return;
}
plugin.setMaintenance(true);
sender.sendMessage(plugin.getPrefix() + "§aStarted timer: §7Maintenance mode will be deactivated in §6" + minutes + " minutes§7.");
plugin.setTaskId(plugin.schedule(new MaintenanceRunnable(plugin, settings, minutes, false)));
plugin.startMaintenanceRunnable(Integer.parseInt(args[1]), false);
sender.sendMessage(settings.getMessage("endtimerStarted").replace("%TIME%", plugin.getRunnable().getTime()));
} else if (args[0].equalsIgnoreCase("starttimer")) {
if (checkPermission(sender, "timer")) return;
if (!isNumeric(args[1])) {
sender.sendMessage(plugin.getPrefix() + "§6/maintenance starttimer <minutes>");
return;
}
if (plugin.isTaskRunning()) {
sender.sendMessage(plugin.getPrefix() + "§cThere's already running a timer!");
if (checkTimerArgs(sender, args[1], "starttimerUsage")) return;
if (plugin.isMaintenance()) {
sender.sendMessage(settings.getMessage("alreadyEnabled"));
return;
}
final int minutes = Integer.parseInt(args[1]);
if (minutes > 40320) {
sender.sendMessage(plugin.getPrefix() + "§cThe number has to be less than 40320 (28 days)!");
return;
}
if (minutes < 1) {
sender.sendMessage(plugin.getPrefix() + "§cThink about running a timer for a negative amount of minutes. Doesn't work §othat §cwell.");
return;
}
sender.sendMessage(plugin.getPrefix() + "§aStarted timer: §7Maintenance mode will be activated in §6" + minutes + " minutes§7.");
plugin.setTaskId(plugin.schedule(new MaintenanceRunnable(plugin, settings, minutes, true)));
plugin.startMaintenanceRunnable(Integer.parseInt(args[1]), true);
sender.sendMessage(settings.getMessage("starttimerStarted").replace("%TIME%", plugin.getRunnable().getTime()));
} else if (args[0].equalsIgnoreCase("timer")) {
if (args[1].equalsIgnoreCase("abort") || args[1].equalsIgnoreCase("stop") || args[1].equalsIgnoreCase("cancel")) {
if (checkPermission(sender, "timer")) return;
if (!plugin.isTaskRunning()) {
sender.sendMessage(plugin.getPrefix() + "§cThere's currently no running timer.");
sender.sendMessage(settings.getMessage("timerNotRunning"));
return;
}
plugin.cancelTask();
sender.sendMessage(plugin.getPrefix() + "§cThe timer has been disabled.");
sender.sendMessage(settings.getMessage("timerCancelled"));
} else
sendUsage(sender);
} else if (args[0].equalsIgnoreCase("add")) {
@@ -134,30 +146,55 @@ public abstract class MaintenanceCommand {
} else if (args[0].equalsIgnoreCase("remove")) {
if (checkPermission(sender, "whitelist.remove")) return;
removePlayerFromWhitelist(sender, args[1]);
} else if (args[0].equalsIgnoreCase("removemotd")) {
if (checkPermission(sender, "setmotd")) return;
if (!isNumeric(args[1])) {
sender.sendMessage(settings.getMessage("removeMotdUsage"));
return;
}
if (settings.getPingMessages().size() < 2) {
sender.sendMessage(settings.getMessage("removeMotdError"));
return;
}
final int index = Integer.parseInt(args[1]);
if (index > settings.getPingMessages().size()) {
sender.sendMessage(settings.getMessage("setMotdIndexError").replace("%MOTDS%", Integer.toString(settings.getPingMessages().size()))
.replace("%NEWAMOUNT%", Integer.toString(settings.getPingMessages().size())));
return;
}
settings.getPingMessages().remove(index - 1);
settings.setToConfig("pingmessages", settings.getPingMessages());
settings.saveConfig();
settings.reloadConfigs();
sender.sendMessage(settings.getMessage("removedMotd").replace("%INDEX%", args[1]));
} else
sendUsage(sender);
} else if (args.length == 3 && plugin.getServerType() == ServerType.BUNGEE) {
handleTimerServerCommands(sender, args);
} else if (args.length > 3 && args[0].equalsIgnoreCase("setmotd")) {
if (checkPermission(sender, "setmotd")) return;
if (!isNumeric(args[1])) {
sender.sendMessage(plugin.getPrefix() + "§cThe first argument has to be the motd index!");
sender.sendMessage(settings.getMessage("setMotdUsage"));
return;
}
final int index = Integer.parseInt(args[1]);
if (index < 1 || index > settings.getPingMessages().size() + 1) {
sender.sendMessage(plugin.getPrefix() + "§cYou currently have " + settings.getPingMessages().size()
+ " motds, so you have to pick a number between 1 and " + (settings.getPingMessages().size() + 1));
sender.sendMessage(settings.getMessage("setMotdIndexError").replace("%MOTDS%", Integer.toString(settings.getPingMessages().size()))
.replace("%NEWAMOUNT%", Integer.toString(settings.getPingMessages().size() + 1)));
return;
}
if (!isNumeric(args[2])) {
sender.sendMessage(plugin.getPrefix() + "§cThe second argument has to be the line number (1 or 2)!");
sender.sendMessage(settings.getMessage("setMotdLineError"));
return;
}
final int line = Integer.parseInt(args[2]);
if (line != 1 && line != 2) {
sender.sendMessage(plugin.getPrefix() + "§cThe second argument has to be the line number (1 or 2)!");
sender.sendMessage(settings.getMessage("setMotdLineError"));
return;
}
@@ -178,51 +215,83 @@ public abstract class MaintenanceCommand {
settings.setToConfig("pingmessages", settings.getPingMessages());
settings.saveConfig();
settings.reloadConfigs();
sender.sendMessage(plugin.getPrefix() + "§aSet line " + line + " of the " + index + ". maintenance motd to §f" + settings.getColoredString(message));
sender.sendMessage(settings.getMessage("setMotd").replace("%LINE%", args[2]).replace("%INDEX%", args[1])
.replace("%MOTD%", "§f" + settings.getColoredString(message)));
} else
sendUsage(sender);
}
private void sendUsage(final SenderInfo sender) {
protected void sendUsage(final SenderInfo sender) {
sendUsage(sender, 1);
}
private static final int COMMANDS_PER_PAGE = 8;
protected void sendUsage(final SenderInfo sender, final int page) {
final List<String> commands = new ArrayList<>();
commandInfos.stream().filter(cmd -> cmd.hasPermission(sender)).forEach(cmd -> {
for (String message : cmd.getMessages()) {
commands.add(message);
}
});
if ((page - 1) * COMMANDS_PER_PAGE > commands.size()) {
sender.sendMessage(plugin.getPrefix() + "§cThere is no page with that number!");
return;
}
final List<String> filteredCommands;
if (page * COMMANDS_PER_PAGE >= commands.size())
filteredCommands = commands.subList((page - 1) * COMMANDS_PER_PAGE, commands.size());
else
filteredCommands = commands.subList((page - 1) * COMMANDS_PER_PAGE, page * COMMANDS_PER_PAGE);
sender.sendMessage("");
sender.sendMessage("§8===========[ §e" + name + " §8| §eVersion: §e" + plugin.getVersion() + " §8]===========");
if (sender.hasPermission("maintenance.reload"))
sender.sendMessage("§6/maintenance reload §7(Reloads the config file, whitelist file and the server-icon)");
if (sender.hasPermission("maintenance.toggle")) {
sender.sendMessage("§6/maintenance on §7(Enables maintenance mode");
sender.sendMessage("§6/maintenance off §7(Disables maintenance mode)");
}
if (sender.hasPermission("maintenance.timer")) {
sender.sendMessage("§6/maintenance starttimer <minutes> §7(After the given time in minutes, maintenance mode will be enabled. Broadcast settings for the timer can be found in the config)");
sender.sendMessage("§6/maintenance endtimer <minutes> §7(Enables maintenance mode. After the given time in minutes, maintenance mode will be disabled)");
sender.sendMessage("§6/maintenance timer abort §7(If running, the current timer will be aborted)");
}
if (sender.hasPermission("maintenance.whitelist.list"))
sender.sendMessage("§6/maintenance whitelist §7(Shows all whitelisted players for the maintenance mode)");
if (sender.hasPermission("maintenance.whitelist.add"))
sender.sendMessage("§6/maintenance add <player> §7(Adds the player to the maintenance whitelist, so they can join the server even though maintenance is enabled)");
if (sender.hasPermission("maintenance.whitelist.remove"))
sender.sendMessage("§6/maintenance remove <player> §7(Removes the player from the maintenance whitelist)");
if (sender.hasPermission("maintenance.setmotd"))
sender.sendMessage("§6/maintenance setmotd <index> <1/2> <message> §7(Sets a motd for maintenance mode)");
if (sender.hasPermission("maintenance.motd"))
sender.sendMessage("§6/maintenance motd §7(Lists the currently set maintenance motds)");
if (sender.hasPermission("maintenance.update"))
sender.sendMessage("§6/maintenance update §7(Remotely downloads the newest version of the plugin onto your server)");
sender.sendMessage("§7Created by §bKennyTV");
sender.sendMessage("§8===========[ §e" + name + " §8| §eVersion: §e" + plugin.getVersion() + " §8]===========");
sender.sendMessage("§8========[ §e" + name + " §8| §eVersion: §e" + plugin.getVersion() + " §8]========");
filteredCommands.forEach(sender::sendMessage);
if (page * 10 < commands.size())
sender.sendMessage("§7Use §b/maintenance help " + (page + 1) + " §7to get to the next help window.");
else
sender.sendMessage("§8× §7Created by §bKennyTV");
sender.sendMessage("§8========[ §e" + name + " §8| §e" + page + "/" + ((commands.size() + getDivide(commands.size())) / COMMANDS_PER_PAGE) + " §8]========");
sender.sendMessage("");
}
private boolean checkPermission(final SenderInfo sender, final String permission) {
if (!sender.hasPermission("maintenance." + permission)) {
sender.sendMessage(settings.getNoPermMessage());
private int getDivide(final int size) {
final int commandSize = size % COMMANDS_PER_PAGE;
return commandSize > 0 ? COMMANDS_PER_PAGE - commandSize : 0;
}
protected boolean checkTimerArgs(final SenderInfo sender, final String time, final String usageKey) {
if (!isNumeric(time)) {
sender.sendMessage(settings.getMessage(usageKey));
return true;
}
if (plugin.isTaskRunning()) {
sender.sendMessage(settings.getMessage("timerAlreadyRunning"));
return true;
}
final int minutes = Integer.parseInt(time);
if (minutes > 40320) {
sender.sendMessage(settings.getMessage("timerTooLong"));
return true;
}
if (minutes < 1) {
sender.sendMessage("§8§o[KennyTV whispers to you] §c§oThink about running a timer for a negative amount of minutes. Doesn't work §lthat §c§owell.");
return true;
}
return false;
}
private boolean isNumeric(final String string) {
protected boolean checkPermission(final SenderInfo sender, final String permission) {
if (!sender.hasPermission("maintenance." + permission)) {
sender.sendMessage(settings.getMessage("noPermission"));
return true;
}
return false;
}
protected boolean isNumeric(final String string) {
try {
Integer.parseInt(string);
} catch (final NumberFormatException nfe) {
@@ -236,4 +305,13 @@ public abstract class MaintenanceCommand {
protected abstract void removePlayerFromWhitelist(SenderInfo sender, String name);
protected abstract void checkForUpdate(SenderInfo sender);
protected void showMaintenanceStatus(SenderInfo sender) {
}
protected void handleToggleServerCommand(SenderInfo sender, String args[]) {
}
protected void handleTimerServerCommands(SenderInfo sender, String args[]) {
}
}
@@ -3,32 +3,24 @@ package eu.kennytv.maintenance.core.runnable;
import eu.kennytv.maintenance.core.MaintenanceModePlugin;
import eu.kennytv.maintenance.core.Settings;
public final class MaintenanceRunnable implements Runnable {
private final MaintenanceModePlugin plugin;
private final Settings settings;
private final boolean enable;
private int minutes;
public final class MaintenanceRunnable extends MaintenanceRunnableBase {
public MaintenanceRunnable(final MaintenanceModePlugin plugin, final Settings settings, final int minutes, final boolean enable) {
this.plugin = plugin;
this.settings = settings;
this.minutes = minutes;
this.enable = enable;
super(plugin, settings, minutes, enable);
}
@Override
public void run() {
if (minutes <= 0) {
plugin.setMaintenance(enable);
if (plugin.isTaskRunning())
plugin.cancelTask();
} else if (settings.getBroadcastIntervalls().contains(minutes)) {
if (enable)
plugin.broadcast(settings.getTimerBroadcastMessage().replaceAll("%MINUTES%", String.valueOf(minutes)));
else
plugin.broadcast(settings.getEndtimerBroadcastMessage().replaceAll("%MINUTES%", String.valueOf(minutes)));
}
protected void finish() {
plugin.setMaintenance(enable);
}
minutes--;
@Override
protected String startMessageKey() {
return settings.getMessage("starttimerBroadcast").replace("%TIME%", getTime());
}
@Override
protected String endMessageKey() {
return settings.getMessage("endtimerBroadcast").replace("%TIME%", getTime());
}
}
@@ -0,0 +1,61 @@
package eu.kennytv.maintenance.core.runnable;
import eu.kennytv.maintenance.core.MaintenanceModePlugin;
import eu.kennytv.maintenance.core.Settings;
public abstract class MaintenanceRunnableBase implements Runnable {
protected final MaintenanceModePlugin plugin;
protected final Settings settings;
protected final boolean enable;
protected int seconds;
protected MaintenanceRunnableBase(final MaintenanceModePlugin plugin, final Settings settings, final int minutes, final boolean enable) {
this.plugin = plugin;
this.settings = settings;
this.seconds = minutes * 60;
this.enable = enable;
}
@Override
public void run() {
if (seconds == 0) {
finish();
} else if (settings.getBroadcastIntervalls().contains(seconds)) {
if (enable)
plugin.broadcast(startMessageKey());
else
plugin.broadcast(endMessageKey());
}
seconds--;
}
protected abstract void finish();
protected abstract String startMessageKey();
protected abstract String endMessageKey();
public String getTime() {
final int preHours = this.seconds / 60;
final int minutes = preHours % 60;
final int seconds = this.seconds % 60;
final StringBuilder buider = new StringBuilder();
append(buider, "hour", preHours / 60);
append(buider, "minute", minutes);
append(buider, "second", seconds);
return buider.toString();
}
private void append(final StringBuilder builder, final String timeUnit, final int time) {
if (time == 0) return;
if (builder.length() != 0)
builder.append(" ");
builder.append(time).append(" ").append(settings.getMessage(time == 1 ? timeUnit : timeUnit + "s"));
}
public int getSecondsLeft() {
return seconds;
}
}
@@ -2,13 +2,13 @@ package eu.kennytv.maintenance.core.util;
import java.util.UUID;
public abstract class SenderInfo {
public interface SenderInfo {
public abstract UUID getUuid();
UUID getUuid();
public abstract String getName();
String getName();
public abstract boolean hasPermission(String permission);
boolean hasPermission(String permission);
public abstract void sendMessage(String message);
void sendMessage(String message);
}
@@ -0,0 +1,7 @@
package eu.kennytv.maintenance.core.util;
public enum ServerType {
BUNGEE,
SPIGOT
}
@@ -0,0 +1,76 @@
package eu.kennytv.maintenance.core.util;
public final class Version implements Comparable<Version> {
private final int[] parts = new int[3];
private final String version;
private final String tag;
public Version(final String version) {
if (version == null || version.isEmpty()) {
this.version = "";
tag = "";
System.out.println("Unknown Maintenance version detected!");
return;
}
final String[] split = version.split("-", 2)[0].split("\\.");
for (int i = 0; i < split.length; i++) {
if (!isNumeric(split[i])) {
this.version = "";
tag = "";
System.out.println("Unknown Maintenance version detected!");
return;
}
parts[i] = Integer.parseInt(split[i]);
}
this.version = version;
tag = version.contains("-") ? version.split("-", 2)[1] : "";
}
/**
* Compare two versions
*
* @param version version to compare to
* @return 0 if they are the same, 1 if this version (not the one to compare to) is newer, -1 if older
*/
@Override
public int compareTo(final Version version) {
if (version == null || version.toString() == null) return 0;
final int max = Math.max(this.parts.length, version.parts.length);
for (int i = 0; i < max; i += 1) {
final int partA = i < this.parts.length ? this.parts[i] : 0;
final int partB = i < version.parts.length ? version.parts[i] : 0;
if (partA < partB) return -1;
if (partA > partB) return 1;
}
if (this.tag.isEmpty() && !version.tag.isEmpty())
return 1;
if (!this.tag.isEmpty() && version.tag.isEmpty())
return -1;
return 0;
}
public String getTag() {
return tag;
}
@Override
public String toString() {
return version;
}
@Override
public boolean equals(final Object o) {
return o instanceof Version && o == this || version.equals(o.toString());
}
private boolean isNumeric(final String string) {
try {
Integer.parseInt(string);
} catch (final NumberFormatException nfe) {
return false;
}
return true;
}
}
@@ -0,0 +1,64 @@
# Maintenance Plugin by KennyTV
# Wörter zwischen dem '%'-Zeichen nur entfernen, wenn Du wirklich weißt, warum Du sie entfernen willst
noPermission: "&cDu hast nicht die erforderliche Berechtigung für diesen Befehl."
maintenanceActivated: "&8[&eMaintenance&8] &6Der Wartungsmodus ist nun aktiviert."
maintenanceDeactivated: "&8[&eMaintenance&8] &6Der Wartungsmodus ist nun deaktiviert."
alreadyEnabled: "&8[&eMaintenance&8] &cDer Wartungsmodus ist bereits aktiviert!"
alreadyDisabled: "&8[&eMaintenance&8] &cDer Wartungsmodus ist bereits deaktiviert!"
helpUsage: "&8[&eMaintenance&8] &c/maintenance help <Seite>"
endtimerBroadcast: "&8[&eMaintenance&8] &7Der Wartungsmodus wird deaktiviert in: &6%TIME%&7."
endtimerStarted: "&8[&eMaintenance&8] &aGestarteter Timer: &7Der Wartungsmodus wird deaktiviert in: &6%TIME%&7."
endtimerUsage: "&8[&eMaintenance&8] &c/maintenance endtimer <Minuten>"
starttimerBroadcast: "&8[&eMaintenance&8] &7Der Wartungsmodus wird aktiviert in: &6%TIME%&7."
starttimerStarted: "&8[&eMaintenance&8] &aGestarteter Timer: &7Der Wartungsmodus wird aktiviert in: &6%TIME%&7"
starttimerUsage: "&8[&eMaintenance&8] &c/maintenance starttimer <Minuten>"
timerAlreadyRunning: "&8[&eMaintenance&8] &cMomentan läuft bereits ein Timer!"
timerNotRunning: "&8[&eMaintenance&8] &cMomentan läuft kein Timer."
timerCancelled: "&8[&eMaintenance&8] &cDer laufende Timer wurde beendet."
timerTooLong: "&8[&eMaintenance&8] &cDie angegebene Nummer muss kleiner als 40320 sein (= 28 Tage)!"
joinNotification: "&8[&eMaintenance&8] &e%PLAYER% &chat versucht den Server beizutreten."
motdList: "&8[&eMaintenance&8] &7Liste der Maintenance MOTDs:"
reload: "&8[&eMaintenance&8] &aConfig, WhitelistedPlayers, Language Datei und Maintenance Icon wurden neugeladen."
removedMotd: "&8[&eMaintenance&8] &aDie %INDEX%. Maintenance MOTD wurde entfernt."
removeMotdError: "&8[&eMaintenance&8] &cDu hast nur eine Maintenance MOTD, daher kannst du auch keine entfernen!"
removeMotdUsage: "&8[&eMaintenance&8] &c/maintenance removemotd <Index>"
serverNotFound: "&8[&eMaintenance&8] &cEs wurde kein Server mit diesem Namen gefunden!"
setMotd: "&8[&eMaintenance&8] &aDie %LINE%. Zeile der %INDEX%. Maintenance MOTD wurde geändert zu: %MOTD%"
setMotdUsage: "&8[&eMaintenance&8] &c/maintenance setmotd <Index> <1/2> <Text>"
setMotdIndexError: "&8[&eMaintenance&8] §cMomentan gibt es %MOTDS% MOTDs, du musst also eine Zahl zwischen 1 and %NEWAMOUNT% wählen."
setMotdLineError: "&8[&eMaintenance&8] &cDas zweite Argument muss die Zeilennummer sein (1 oder 2)!"
updateDownloading: "&8[&eMaintenance&8] &c&lUpdate wird heruntergeladen..."
updateFailed: "&8[&eMaintenance&8] &4&lUpdate fehlgeschlagen!"
updateFinished: "&8[&eMaintenance&8] &a&lDas Update war erfolgreich! Um Probleme mit Timern zu vermeiden und das Update zu vervollständigen, musst du den Server neustarten!"
whitelistedPlayers: "&8[&eMaintenance&8] &6Spieler in der Maintenance Whitelist:"
whitelistedPlayersFormat: "&8- &e%NAME% &8(&7%UUID%&8)"
whitelistAdded: "&8[&eMaintenance&8] &b%PLAYER% &awurde zur Maintenance Whitelist hinzugefügt!"
whitelistAlreadyAdded: "&8[&eMaintenance&8] &b%PLAYER% &cist bereits in der Maintenance Whitelist!"
whitelistRemoved: "&8[&eMaintenance&8] &b%PLAYER% &awurde von der Maintenance Whitelist entfernt!"
whitelistNotFound: "&8[&eMaintenance&8] &cDieser Spieler ist nicht in der Maintenance Whitelist!"
whitelistEmtpy: "&8[&eMaintenance&8] &cDie Maintenance Whitelist ist leer! Nutze '/maintenance add <Spieler>', um jemanden hinzuzufügen!"
whitelistEmptyDefault: "&8[&eMaintenance&8] &cNutze '/maintenance add <player>', um jemanden hinzuzufügen. Ansonsten kannst auch die UUID des Spielers in die WhitelistedPlayers.yml einsetzen, wie es im dortigen Beispiel schon drinsteht!"
playerNotFound: "&8[&eMaintenance&8] &cBisher hat kein Spieler mit diesem Namen jemals auf diesem Server gespielt."
playerNotOnline: "&8[&eMaintenance&8] &cEs ist momentan kein Spieler mit diesem Namen online."
second: "Sekunde"
seconds: "Sekunden"
minute: "Minute"
minutes: "Minuten"
hour: "Stunde"
hours: "Stunden"
# Nachrichten für den Bungee Teil des Plugins, einfach ignorieren, falls das Plugin auf Spigot verwendet wird
singleEndtimerBroadcast: "&8[&eMaintenance&8] &7Der Wartungsmodus auf Server %SERVER% wird deaktiviert in: &6%TIME%&7."
singleEndtimerUsage: "&8[&eMaintenance&8] &c/maintenance endtimer <Server> <Minuten>"
singleStarttimerBroadcast: "&8[&eMaintenance&8] &7Der Wartungsmodus auf Server %SERVER% wird aktiviert in: &6%TIME%&7."
singleStarttimerUsage: "&8[&eMaintenance&8] &c/maintenance starttimer <Server> <Minuten>"
singleMaintenanceKick: "&8[&eMaintenance&8] &cDer Server %SERVER% befindet sich momentan im Wartungsmodus! Probier es später nochmal!"
singleMaintenanceKickComplete: "&cDer Server %SERVER% befindet sich in Wartung!%NEWLINE%&cDu kannst versuchen zu rejoinen, um andere Server zu betreten!"
singleMaintenanceActivated: "&8[&eMaintenance&8] &6Der Wartungsmodus wurde auf &e%SERVER% &6aktiviert."
singleMaintenanceDeactivated: "&8[&eMaintenance&8] &6Der Wartungsmodus wurde auf &e%SERVER% &6deaktiviert."
singleServerAlreadyEnabled: "&8[&eMaintenance&8] &cDer Wartungsmodus ist bereits an auf &e%SERVER%&c!"
singleServerAlreadyDisabled: "&8[&eMaintenance&8] &cDer Wartungsmodus ist bereits aus auf &e%SERVER%&c!"
singleServerMaintenanceList: "&8[&eMaintenance&8] &7Unterserverserver, die im Wartungsmodus sind:"
singleServerMaintenanceListEmpty: "&8[&eMaintenance&8] &7Es befindet sich momentan kein Unterserver im Wartungsmodus."
@@ -0,0 +1,64 @@
# Maintenance Plugin by KennyTV
# Don't remove words inbetween the '%' if you don't exactly know why you're doing it
noPermission: "&cYou do not have the permission to execute that command."
maintenanceActivated: "&8[&eMaintenance&8] &6Maintenance mode is now activated."
maintenanceDeactivated: "&8[&eMaintenance&8] &6Maintenance mode is now deactivated."
alreadyEnabled: "&8[&eMaintenance&8] &cMaintenance is already enabled!"
alreadyDisabled: "&8[&eMaintenance&8] &cMaintenance is already disabled!"
helpUsage: "&8[&eMaintenance&8] &c/maintenance help <page>"
endtimerBroadcast: "&8[&eMaintenance&8] &7Maintenance mode will be disabled in &6%TIME%&7."
endtimerStarted: "&8[&eMaintenance&8] &aStarted timer: &7Maintenance mode will be deactivated in &6%TIME%&7."
endtimerUsage: "&8[&eMaintenance&8] &c/maintenance endtimer <minutes>"
starttimerBroadcast: "&8[&eMaintenance&8] &7Maintenance mode will be enabled in &6%TIME%&7."
starttimerStarted: "&8[&eMaintenance&8] &aStarted timer: &7Maintenance mode will be activated in &6%TIME%&7."
starttimerUsage: "&8[&eMaintenance&8] &c/maintenance starttimer <minutes>"
timerAlreadyRunning: "&8[&eMaintenance&8] &cThere's already a timer scheduled!"
timerNotRunning: "&8[&eMaintenance&8] &cThere's currently no running timer."
timerCancelled: "&8[&eMaintenance&8] &cThe current timer has been disabled."
timerTooLong: "&8[&eMaintenance&8] &cThe number has to be less than 40320 (28 days)!"
joinNotification: "&8[&eMaintenance&8] &e%PLAYER% &ctried to join the server."
motdList: "&8[&eMaintenance&8] &7List of your maintenance motds:"
reload: "&8[&eMaintenance&8] &aReloaded config, whitelistedplayers, language file and the maintenance icon."
removedMotd: "&8[&eMaintenance&8] &aRemoved motd number %INDEX%."
removeMotdError: "&8[&eMaintenance&8] &cYou only have one motd, so you can't remove any!"
removeMotdUsage: "&8[&eMaintenance&8] &c/maintenance removemotd <index>"
serverNotFound: "&8[&eMaintenance&8] &cNo server with this name is registered on the proxy!"
setMotd: "&8[&eMaintenance&8] &aSet line %LINE% of the %INDEX%. maintenance motd to %MOTD%"
setMotdUsage: "&8[&eMaintenance&8] &c/maintenance setmotd <index> <1/2> <message>"
setMotdIndexError: "&8[&eMaintenance&8] §cYou currently have %MOTDS% motds, so you have to pick a number between 1 and %NEWAMOUNT%."
setMotdLineError: "&8[&eMaintenance&8] &cThe second argument has to be the line number (1 or 2)!"
updateDownloading: "&8[&eMaintenance&8] &c&lDownloading update..."
updateFailed: "&8[&eMaintenance&8] &4&lUpdate failed!"
updateFinished: "&8[&eMaintenance&8] &a&lThe update was successful! To prevent issues with tasks and to complete the update, you have to restart the server!"
whitelistedPlayers: "&8[&eMaintenance&8] &6Whitelisted players for maintenance:"
whitelistedPlayersFormat: "&8- &e%NAME% &8(&7%UUID%&8)"
whitelistAdded: "&8[&eMaintenance&8] &aAdded &b%PLAYER% &ato the maintenance whitelist!"
whitelistAlreadyAdded: "&8[&eMaintenance&8] &b%PLAYER% &calready is in the maintenance whitelist!"
whitelistRemoved: "&8[&eMaintenance&8] &aRemoved &b%PLAYER% &afrom the maintenance whitelist!"
whitelistNotFound: "&8[&eMaintenance&8] &cThis player is not in the maintenance whitelist!"
whitelistEmtpy: "&8[&eMaintenance&8] &cThe maintenance whitelist is empty! Use '/maintenance add <player>' to add someone!"
whitelistEmptyDefault: "&8[&eMaintenance&8] &cUse '/maintenance add <player>' to add someone. Alternatively, you can add the uuid of a player to the WhitelistedPlayers.yml as seen in the example in the file!"
playerNotFound: "&8[&eMaintenance&8] &cNo player with this name has played on this server before."
playerNotOnline: "&8[&eMaintenance&8] &cThere's no player online with that name."
second: "second"
seconds: "seconds"
minute: "minute"
minutes: "minutes"
hour: "hour"
hours: "hours"
# Some messages for the Bungee part, just ignore them if you use the plugin on Spigot
singleEndtimerBroadcast: "&8[&eMaintenance&8] &7Maintenance mode on server %SERVER% will be disabled in &6%TIME%&7."
singleEndtimerUsage: "&8[&eMaintenance&8] &c/maintenance endtimer <server> <minutes>"
singleStarttimerBroadcast: "&8[&eMaintenance&8] &7Maintenance mode on server %SERVER% will be enabled in &6%TIME%&7."
singleStarttimerUsage: "&8[&eMaintenance&8] &c/maintenance starttimer <server> <minutes>"
singleMaintenanceKick: "&8[&eMaintenance&8] &cThe server %SERVER% is currently under maintenance! Try again later!"
singleMaintenanceKickComplete: "&cThe server %SERVER% is under maintenance!%NEWLINE%&cYou may try to rejoin to go onto another server!"
singleMaintenanceActivated: "&8[&eMaintenance&8] &6Maintenance mode is now activated on server &e%SERVER%&6."
singleMaintenanceDeactivated: "&8[&eMaintenance&8] &6Maintenance mode is now deactivated on server &e%SERVER%&6."
singleServerAlreadyEnabled: "&8[&eMaintenance&8] &cMaintenance is already enabled on server &e%SERVER%&c!"
singleServerAlreadyDisabled: "&8[&eMaintenance&8] &cMaintenance is already disabled on server &e%SERVER%&c!"
singleServerMaintenanceList: "&8[&eMaintenance&8] &7Proxied servers, that have maintenance enabled:"
singleServerMaintenanceListEmpty: "&8[&eMaintenance&8] &7There are no proxied servers that are under maintenance."
+1 -1
View File
@@ -6,7 +6,7 @@
<parent>
<artifactId>maintenance-base</artifactId>
<groupId>eu.kennytv</groupId>
<version>2.3.1</version>
<version>2.5</version>
</parent>
<artifactId>maintenance-parent</artifactId>
+3 -3
View File
@@ -6,7 +6,7 @@
<parent>
<artifactId>maintenance-base</artifactId>
<groupId>eu.kennytv</groupId>
<version>2.3.1</version>
<version>2.5</version>
</parent>
<artifactId>maintenance-spigot</artifactId>
@@ -33,7 +33,7 @@
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.12.2-R0.1-SNAPSHOT</version>
<version>1.13.1-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -45,7 +45,7 @@
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib-API</artifactId>
<version>4.3.0</version>
<version>4.4.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
@@ -2,9 +2,10 @@ package eu.kennytv.maintenance.spigot;
import eu.kennytv.maintenance.api.IMaintenance;
import eu.kennytv.maintenance.api.ISettings;
import eu.kennytv.maintenance.api.MaintenanceSpigotAPI;
import eu.kennytv.maintenance.api.spigot.MaintenanceSpigotAPI;
import eu.kennytv.maintenance.core.MaintenanceModePlugin;
import eu.kennytv.maintenance.core.hook.ServerListPlusHook;
import eu.kennytv.maintenance.core.util.ServerType;
import eu.kennytv.maintenance.spigot.command.MaintenanceSpigotCommand;
import eu.kennytv.maintenance.spigot.listener.PlayerLoginListener;
import eu.kennytv.maintenance.spigot.metrics.MetricsLite;
@@ -24,12 +25,13 @@ public final class MaintenanceSpigotPlugin extends MaintenanceModePlugin {
private final SettingsSpigot settings;
MaintenanceSpigotPlugin(final MaintenanceSpigotBase plugin) {
super("§8[§eMaintenanceSpigot§8] ", plugin.getDescription().getVersion());
super("§8[§eMaintenanceSpigot§8] ", plugin.getDescription().getVersion(), ServerType.SPIGOT);
this.plugin = plugin;
settings = new SettingsSpigot(plugin);
settings = new SettingsSpigot(this, plugin);
plugin.getLogger().info("Plugin by KennyTV");
plugin.getLogger().info(getUpdateMessage());
plugin.getCommand("maintenancespigot").setExecutor(new MaintenanceSpigotCommand(this, settings));
final PluginManager pm = getServer().getPluginManager();
@@ -63,14 +65,14 @@ public final class MaintenanceSpigotPlugin extends MaintenanceModePlugin {
getServer().getOnlinePlayers().stream()
.filter(p -> !p.hasPermission("maintenance.bypass") && !settings.getWhitelistedPlayers().containsKey(p.getUniqueId()))
.forEach(p -> p.kickPlayer(settings.getKickMessage().replace("%NEWLINE%", "\n")));
getServer().broadcastMessage(settings.getMaintenanceActivated());
getServer().broadcastMessage(settings.getMessage("maintenanceActivated"));
} else
getServer().broadcastMessage(settings.getMaintenanceDeactivated());
getServer().broadcastMessage(settings.getMessage("maintenanceDeactivated"));
}
@Override
public int schedule(final Runnable runnable) {
return getServer().getScheduler().scheduleSyncRepeatingTask(plugin, runnable, 0, 1200);
public int startMaintenanceRunnable(final Runnable runnable) {
return getServer().getScheduler().scheduleSyncRepeatingTask(plugin, runnable, 0, 20);
}
@Override
@@ -81,7 +83,8 @@ public final class MaintenanceSpigotPlugin extends MaintenanceModePlugin {
@Override
public void cancelTask() {
getServer().getScheduler().cancelTask(taskId);
setTaskId(0);
runnable = null;
taskId = 0;
}
@Override
@@ -19,9 +19,11 @@ public final class SettingsSpigot extends Settings {
private final MaintenanceSpigotBase plugin;
private final IPingListener pingListener;
private FileConfiguration config;
private FileConfiguration language;
private FileConfiguration whitelist;
SettingsSpigot(final MaintenanceSpigotBase plugin) {
SettingsSpigot(final MaintenanceSpigotPlugin pl, final MaintenanceSpigotBase plugin) {
super(pl);
this.plugin = plugin;
final PluginManager pm = plugin.getServer().getPluginManager();
@@ -33,10 +35,56 @@ public final class SettingsSpigot extends Settings {
pingListener = listener;
}
createFiles();
if (!plugin.getDataFolder().exists())
plugin.getDataFolder().mkdirs();
createFile("spigot-config.yml");
createFile("WhitelistedPlayers.yml");
reloadConfigs();
}
private void createFile(final String name) {
final File file = new File(plugin.getDataFolder(), name);
if (!file.exists()) {
try (final InputStream in = plugin.getResource(name)) {
Files.copy(in, file.toPath());
} catch (final IOException e) {
throw new RuntimeException("Unable to create " + name + " file for Maintenance!", e);
}
}
}
private void createAndLoadLanguageFile() {
final File file = new File(plugin.getDataFolder(), "language-" + getLanguage() + ".yml");
if (!file.exists()) {
try (final InputStream in = plugin.getResource("language-" + getLanguage() + ".yml")) {
Files.copy(in, file.toPath());
} catch (final IOException e) {
plugin.getLogger().warning("Unable to provide language " + getLanguage());
if (!languageName.equals("en")) {
plugin.getLogger().warning("Falling back to default language: en");
languageName = "en";
createAndLoadLanguageFile();
return;
}
}
}
try {
language = YamlConfiguration.loadConfiguration(new InputStreamReader(new FileInputStream(new File(plugin.getDataFolder(), "language-" + getLanguage() + ".yml")), StandardCharsets.UTF_8));
} catch (final IOException e) {
throw new RuntimeException("Unable to load Maintenance language file!", e);
}
}
@Override
public boolean updateExtraConfig() {
// Remove MySQL part from default config
/*if (configContains("mysql")) {
setToConfig("mysql", null);
return true;
}*/
return false;
}
@Override
public void saveConfig() {
try {
@@ -57,15 +105,15 @@ public final class SettingsSpigot extends Settings {
@Override
public void reloadConfigs() {
final File file = new File(plugin.getDataFolder(), "spigot-config.yml");
try {
config = YamlConfiguration.loadConfiguration(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8));
config = YamlConfiguration.loadConfiguration(new InputStreamReader(new FileInputStream(new File(plugin.getDataFolder(), "spigot-config.yml")), StandardCharsets.UTF_8));
whitelist = YamlConfiguration.loadConfiguration(new File(plugin.getDataFolder(), "WhitelistedPlayers.yml"));
} catch (final IOException e) {
throw new RuntimeException("Unable to load spigot-config.yml!", e);
throw new RuntimeException("Unable to load Maintenance files!", e);
}
loadSettings();
createAndLoadLanguageFile();
}
@Override
@@ -79,31 +127,6 @@ public final class SettingsSpigot extends Settings {
whitelist.set(uuid, s);
}
@Override
public boolean createFiles() {
if (!plugin.getDataFolder().exists())
plugin.getDataFolder().mkdirs();
final File file = new File(plugin.getDataFolder(), "spigot-config.yml");
if (!file.exists()) {
try (final InputStream in = plugin.getResource("spigot-config.yml")) {
Files.copy(in, file.toPath());
} catch (final IOException e) {
throw new RuntimeException("Unable to create spigot-config.yml file for Maintenance!", e);
}
}
final File whitelistFile = new File(plugin.getDataFolder(), "WhitelistedPlayers.yml");
if (!whitelistFile.exists()) {
try (final InputStream in = plugin.getResource("WhitelistedPlayers.yml")) {
Files.copy(in, whitelistFile.toPath());
} catch (final IOException e) {
throw new RuntimeException("Unable to create WhitelistedPlayers.yml file for Maintenance!", e);
}
}
return true;
}
@Override
public String getConfigString(final String path) {
final String s = config.getString(path);
@@ -111,6 +134,16 @@ public final class SettingsSpigot extends Settings {
plugin.getLogger().warning("The config is missing the following string: " + path);
return "null";
}
return s;
}
@Override
public String getMessage(final String path) {
final String s = language.getString(path);
if (s == null) {
plugin.getLogger().warning("The language file is missing the following string: " + path);
return "null";
}
return ChatColor.translateAlternateColorCodes('&', s);
}
@@ -28,48 +28,52 @@ public final class MaintenanceSpigotCommand extends MaintenanceCommand implement
protected void addPlayerToWhitelist(final SenderInfo sender, final String name) {
final Player selected = Bukkit.getPlayer(name);
if (selected != null) {
settings.addWhitelistedPlayer(selected.getUniqueId(), selected.getName());
sender.sendMessage(plugin.getPrefix() + "§aAdded §b" + selected.getName() + " §ato the maintenance whitelist!");
if (settings.addWhitelistedPlayer(selected.getUniqueId(), selected.getName()))
sender.sendMessage(settings.getMessage("whitelistAdded").replace("%PLAYER%", selected.getName()));
else
sender.sendMessage(settings.getMessage("whitelistAlreadyAdded").replace("%PLAYER%", selected.getName()));
return;
}
final OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(name);
if (!offlinePlayer.hasPlayedBefore()) {
sender.sendMessage(plugin.getPrefix() + "§cNo player with this name has played on this server before.");
sender.sendMessage(settings.getMessage("playerNotFound"));
return;
}
if (settings.addWhitelistedPlayer(offlinePlayer.getUniqueId(), offlinePlayer.getName()))
sender.sendMessage(plugin.getPrefix() + "§aAdded §b" + offlinePlayer.getName() + " §ato the maintenance whitelist!");
sender.sendMessage(settings.getMessage("whitelistAdded").replace("%PLAYER%", offlinePlayer.getName()));
else
sender.sendMessage(plugin.getPrefix() + "§b" + offlinePlayer.getName() + " §calready is in the maintenance whitelist!");
sender.sendMessage(settings.getMessage("whitelistAlreadyAdded").replace("%PLAYER%", offlinePlayer.getName()));
}
@Override
protected void removePlayerFromWhitelist(final SenderInfo sender, final String name) {
final Player selected = Bukkit.getPlayer(name);
if (selected != null) {
settings.removeWhitelistedPlayer(selected.getUniqueId());
sender.sendMessage(plugin.getPrefix() + "§aRemoved §b" + selected.getName() + " §afrom the maintenance whitelist!");
if (settings.removeWhitelistedPlayer(selected.getUniqueId()))
sender.sendMessage(settings.getMessage("whitelistRemoved").replace("%PLAYER%", selected.getName()));
else
sender.sendMessage(settings.getMessage("whitelistNotFound"));
return;
}
final OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(name);
if (!offlinePlayer.hasPlayedBefore()) {
sender.sendMessage(plugin.getPrefix() + "§cNo player with this name has played on this server before.");
sender.sendMessage(settings.getMessage("playerNotFound"));
return;
}
if (settings.removeWhitelistedPlayer(offlinePlayer.getUniqueId()))
sender.sendMessage(plugin.getPrefix() + "§aRemoved §b" + offlinePlayer.getName() + " §afrom the maintenance whitelist!");
sender.sendMessage(settings.getMessage("whitelistRemoved").replace("%PLAYER%", offlinePlayer.getName()));
else
sender.sendMessage(plugin.getPrefix() + "§cThis player is not in the maintenance whitelist!");
sender.sendMessage(settings.getMessage("whitelistNotFound"));
}
@Override
protected void checkForUpdate(final SenderInfo sender) {
if (plugin.updateAvailable()) {
sender.sendMessage(plugin.getPrefix() + "§cNewest version available: §aVersion " + plugin.getNewestVersion() + "§c, you're still on §a" + plugin.getVersion());
sender.sendMessage(plugin.getPrefix() + "§cNewest version available: §aVersion " + plugin.getNewestVersion() + "§c, you're on §a" + plugin.getVersion());
sender.sendMessage(plugin.getPrefix() + "§c§lWARNING: §cYou will have to restart the server to prevent further issues and to complete the update!" +
" If you can't do that, don't update!");
sender.sendMessage(plugin.getPrefix() + "§eUse §c§l/maintenance forceupdate §eto update!");
@@ -7,13 +7,13 @@ import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.comphenix.protocol.wrappers.WrappedServerPing;
import com.google.common.collect.Lists;
import eu.kennytv.maintenance.core.listener.IPingListener;
import eu.kennytv.maintenance.spigot.MaintenanceSpigotBase;
import eu.kennytv.maintenance.spigot.SettingsSpigot;
import javax.imageio.ImageIO;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@@ -30,11 +30,16 @@ public final class PacketListener implements IPingListener {
if (!settings.isMaintenance()) return;
final WrappedServerPing ping = event.getPacket().getServerPings().read(0);
ping.setVersionProtocol(0);
ping.setMotD(settings.getRandomPingMessage());
ping.setVersionName(settings.getPlayerCountMessage());
final List<WrappedGameProfile> players = Lists.newArrayList();
if (settings.hasCustomPlayerCountMessage()) {
ping.setVersionProtocol(0);
ping.setVersionName(settings.getPlayerCountMessage()
.replace("%ONLINE%", Integer.toString(pl.getServer().getOnlinePlayers().size()))
.replace("%MAX%", Integer.toString(pl.getServer().getMaxPlayers())));
}
final List<WrappedGameProfile> players = new ArrayList<>();
for (final String string : settings.getPlayerCountHoverMessage().split("%NEWLINE%"))
players.add(new WrappedGameProfile(UUID.randomUUID(), string));
ping.setPlayers(players);
@@ -13,14 +13,14 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerLoginEvent;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
public final class PlayerLoginListener implements Listener {
private final MaintenanceSpigotPlugin plugin;
private final SettingsSpigot settings;
private final Set<UUID> notifiedPlayers = new HashSet<>();
public PlayerLoginListener(final MaintenanceSpigotPlugin plugin, final SettingsSpigot settings) {
this.plugin = plugin;
@@ -39,21 +39,19 @@ public final class PlayerLoginListener implements Listener {
if (settings.isJoinNotifications())
Bukkit.getOnlinePlayers().stream().filter(player -> player.hasPermission("maintenance.joinnotification"))
.forEach(player -> player.sendMessage(settings.getJoinNotification().replace("%PLAYER%", p.getName())));
.forEach(player -> player.sendMessage(settings.getMessage("joinNotification").replace("%PLAYER%", p.getName())));
return;
}
}
if (!p.hasPermission("maintenance.admin")) return;
if (!p.hasPermission("maintenance.admin") || notifiedPlayers.contains(p.getUniqueId())) return;
plugin.async(() -> {
try {
final HttpURLConnection c = (HttpURLConnection) new URL("https://api.spigotmc.org/legacy/update.php?resource=40699").openConnection();
final String newVersion = new BufferedReader(new InputStreamReader(c.getInputStream())).readLine();
if (!newVersion.equals(plugin.getVersion())) {
p.sendMessage(plugin.getPrefix() + "§cThere is a newer version available: §aVersion " + newVersion + "§c, you're still on §a" + plugin.getVersion());
if (plugin.updateAvailable()) {
p.sendMessage(plugin.getPrefix() + "§cThere is a newer version available: §aVersion " + plugin.getNewestVersion() + "§c, you're on §a" + plugin.getVersion());
notifiedPlayers.add(p.getUniqueId());
try {
final TextComponent tc1 = new TextComponent(TextComponent.fromLegacyText(plugin.getPrefix()));
final TextComponent tc2 = new TextComponent(TextComponent.fromLegacyText("§cDownload it at: §6https://www.spigotmc.org/resources/maintenancemode.40699/"));
final TextComponent click = new TextComponent(TextComponent.fromLegacyText(" §7§l§o(CLICK ME)"));
@@ -63,8 +61,9 @@ public final class PlayerLoginListener implements Listener {
tc1.addExtra(click);
p.spigot().sendMessage(tc1);
} catch (final Exception e) {
p.sendMessage(plugin.getPrefix() + "§cDownload it at: §6https://www.spigotmc.org/resources/maintenancemode.40699/");
}
} catch (final Exception ignored) {
}
});
}
@@ -6,7 +6,7 @@ import org.bukkit.entity.Player;
import java.util.UUID;
public final class BukkitSenderInfo extends SenderInfo {
public final class BukkitSenderInfo implements SenderInfo {
private final CommandSender sender;
public BukkitSenderInfo(final CommandSender sender) {
@@ -1,5 +1,5 @@
# MaintenanceSpigot Plugin by KennyTV
# Version ${project.version}
# Important note: To use this plugin to its full extend, it requires the plugin 'ProtocolLib'
# Enables maintenance-mode.
enable-maintenance-mode: false
@@ -10,32 +10,30 @@ pingmessages:
- "&cMaintenance mode!%NEWLINE%&6We will be back soon!"
#- "Another entry"
# Is shown at the top right corner of the server in the serverlist,
# If set to true, the message below will be shown at the top right corner of the server in the serverlist,
# where the playercount would normally be displayed.
# If set to false, the normal playercount will be shown.
# Alternatively you can use '%ONLINE%' and '%MAX% if you want to include the playercount in a custom message (e.g. '&cMaintenance &7%ONLINE%&8/&7%MAX%').
enable-playercountmessage: true
playercountmessage: "&4Maintenance"
# Is shown when you move your mouse above the text at the top right corner of the server in the serverlist,
# where the playercount would normally be displayed.
playercounthovermessage: "&cCurrently under%NEWLINE%&cmaintenance"
# Will be shown, when a player tries to join on the server without the permission.
# Is shown when a player tries to join while maintenance is enabled and they don't have the permission to bypass it.
kickmessage: "&cThe server is currently under maintenance!%NEWLINE%Try again later!"
# Some self explanatory messages
no-permission: "&cYou do not have the permission to execute that command."
maintenance-activated: "&6Maintenance mode is now activated."
maintenance-deactivated: "&6Maintenance mode is now deactivated."
starttimer-broadcast-mesage: '&8[&eMaintenance&8] &7Maintenance mode will be enabled in &6%MINUTES% minutes&7.'
endtimer-broadcast-mesage: '&8[&eMaintenance&8] &7Maintenance mode will be disabled in &6%MINUTES% minutes&7.'
# If using the timer command: In what intervalls before enabling/disabling maintenance there will be a broadcast.
timer-broadcasts-for-minutes: [60, 30, 15, 10, 5, 4, 3, 2, 1]
timer-broadcast-for-seconds: [1200, 900, 600, 300, 120, 60, 30, 20, 10, 5, 4, 3, 2, 1]
# If set to true, players with the maintenance.joinnotification permission will receive a message,
# that a player tried to join the server while maintenance is enabled.
send-join-notification: false
join-notification: "&e%PLAYER% &ctried to join the server."
# If set to true, the server icon will be changed to maintenance-icon.png in the Bungee main/base-folder.
custom-maintenance-icon: false
custom-maintenance-icon: false
# Changes the language of command feedback/messages.
# Currently available are: en (English), de (German)
language: en
+14 -2
View File
@@ -6,7 +6,7 @@
<groupId>eu.kennytv</groupId>
<artifactId>maintenance-base</artifactId>
<version>2.3.1</version>
<version>2.5</version>
<name>Maintenance</name>
<packaging>pom</packaging>
@@ -31,13 +31,25 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<version>3.2.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<relocations>
<relocation>
<pattern>com.zaxxer.hikari</pattern>
<shadedPattern>eu.kennytv.lib.hikari</shadedPattern>
</relocation>
<!--<relocation>
<pattern>org.slf4j</pattern>
<shadedPattern>eu.kennytv.lib.slf4j</shadedPattern>
</relocation>-->
</relocations>
</configuration>
</execution>
</executions>
</plugin>