├── .gitattributes ├── .github └── ISSUE_TEMPLATE │ ├── other-template.md │ ├── feature_request.md │ └── bug_report.md ├── src └── cloud │ └── bolte │ └── serverlistmotd │ ├── variables │ ├── RandomNumberVariable.java │ ├── TimeVariable.java │ ├── WeatherVariable.java │ ├── MoneyVariable.java │ ├── PlayerVariable.java │ └── RandomPlayerVariable.java │ ├── events │ ├── RestrictedModeJoin.java │ ├── Ping.java │ ├── IpLogging.java │ └── ProtocolLibImplementation.java │ ├── motd │ ├── Motd.java │ ├── MotdState.java │ ├── ClassicMotd.java │ ├── RandomMotd.java │ ├── RestrictedModeMotd.java │ ├── WhitelistMotd.java │ ├── BanManagerMotd.java │ ├── BanMotd.java │ └── MaxBansMotd.java │ ├── util │ ├── VaultIntegration.java │ ├── PapiIntegration.java │ ├── Gradient.java │ ├── IO.java │ └── HexResolver.java │ ├── slots │ ├── FakeOnlinePlayer.java │ ├── OnlineMultiplier.java │ ├── SlotsPlusOne.java │ ├── OutdatedClientText.java │ ├── HoverText.java │ └── VersionText.java │ ├── ban │ ├── BanInterface.java │ ├── SpigotBan.java │ ├── MaxBansPlugin.java │ └── BanManager.java │ ├── Main.java │ ├── cmd │ └── Serverlist.java │ └── SpigotConfig.java ├── plugin.yml ├── README.md ├── config.yml └── LICENSE.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/other-template.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Other template 3 | about: Something else you want to say/ ask 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: feature 6 | assignees: strumswell 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: strumswell 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Config** 24 | Please attach a copy of your config.yml, e.g. via Pastebin. 25 | 26 | **Versions (please complete the following information):** 27 | - Spigot 28 | - ServerlistMOTD 29 | - ProtocolLib 30 | 31 | **Additional context** 32 | Add any other context about the problem here. 33 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/variables/RandomNumberVariable.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.variables; 2 | 3 | import java.util.Random; 4 | 5 | import cloud.bolte.serverlistmotd.SpigotConfig; 6 | 7 | public class RandomNumberVariable { 8 | 9 | private final static Random random = new Random(); 10 | 11 | private RandomNumberVariable() { 12 | throw new IllegalStateException("Utility class"); 13 | } 14 | 15 | /** 16 | * Get a random number based on min/ max from config 17 | * Only used in VersionText at the moment which you 18 | * can use to fake an online count / slots 19 | * @return random number 20 | */ 21 | public static int getRandomNumber() { 22 | return random.nextInt(SpigotConfig.getRandomMax() - SpigotConfig.getRandomMin()) + SpigotConfig.getRandomMin(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /plugin.yml: -------------------------------------------------------------------------------- 1 | name: ServerlistMOTD 2 | author: Strumswell 3 | version: X-2021-11-23 4 | description: Change your Serverlist Motd! 5 | load: POSTWORLD 6 | softdepend: [ProtocolLib, Vault, PlaceholderAPI, BanManager, MaxBans, MultiVerse, Multiverse-Core, Multiverse-Portals, Multiverse-NetherPortals, Multiverse-Inventories, Towny, Essentials] 7 | main: cloud.bolte.serverlistmotd.Main 8 | commands: 9 | serverlist: 10 | description: Show list of commands 11 | aliases: [sl, smotd] 12 | permission: serverlist 13 | permission-message: §e§oServerlist§6§lMOTD §7> §cYou don't have permissions! 14 | usage: §e§oServerlist§6§lMOTD §7> §cWrong syntax! See /serverlist 15 | permissions: 16 | serverlist.*: 17 | description: Gives access to all commands 18 | children: 19 | serverlist: true 20 | serverlist.reload: true 21 | serverlist.restrictedmode: true 22 | serverlist.versiontext: true 23 | serverlist.banmotd: true 24 | serverlist.whitelistmotd: true 25 | serverlist.randommotd: true -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/events/RestrictedModeJoin.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.events; 2 | 3 | import org.bukkit.event.EventHandler; 4 | import org.bukkit.event.Listener; 5 | import org.bukkit.event.player.PlayerLoginEvent; 6 | import org.bukkit.event.player.PlayerLoginEvent.Result; 7 | 8 | import cloud.bolte.serverlistmotd.SpigotConfig; 9 | 10 | /* 11 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 12 | * ServerlistMOTD is licensed under a 13 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 14 | * 15 | * You should have received a copy of the license along with this work. 16 | * If not, see . 17 | */ 18 | 19 | public class RestrictedModeJoin implements Listener{ 20 | @EventHandler 21 | public void logInRestrictedMode(PlayerLoginEvent e) { 22 | if (SpigotConfig.restrictedModeEnabled()) { 23 | if (e.getPlayer().isOp() || e.getPlayer().hasPermission("serverlist.restrictedmode.join")) { 24 | e.allow(); 25 | } else e.disallow(Result.KICK_OTHER, SpigotConfig.getRestrictedKickMessage()); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/variables/TimeVariable.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.variables; 2 | 3 | import org.bukkit.Bukkit; 4 | 5 | import cloud.bolte.serverlistmotd.SpigotConfig; 6 | 7 | /* 8 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 9 | * ServerlistMOTD is licensed under a 10 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 11 | * 12 | * You should have received a copy of the license along with this work. 13 | * If not, see . 14 | */ 15 | 16 | public class TimeVariable { 17 | 18 | private TimeVariable() { 19 | throw new IllegalStateException("Utility class"); 20 | } 21 | 22 | /** 23 | * Checks wethaer in world specified in config 24 | * @return day/night text from config 25 | */ 26 | public static String getTime() { 27 | String currentTime = Bukkit.getServer().getWorld(SpigotConfig.getTimeWorld()).getTime()+""; 28 | int time = Integer.parseInt(currentTime); 29 | 30 | if (time < 12000) { 31 | return SpigotConfig.getDayText(); 32 | } else { 33 | return SpigotConfig.getNightText(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/motd/Motd.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.motd; 2 | 3 | import java.net.InetAddress; 4 | 5 | import org.bukkit.event.server.ServerListPingEvent; 6 | 7 | /* 8 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 9 | * ServerlistMOTD is licensed under a 10 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 11 | * 12 | * You should have received a copy of the license along with this work. 13 | * If not, see . 14 | */ 15 | 16 | public interface Motd { 17 | 18 | /** 19 | * Get unformatted motd string 20 | * @param ip IP address of user 21 | * @return unformatted motd 22 | */ 23 | String getMOTD(InetAddress ip); 24 | 25 | /** 26 | * Format motd string with color and vars 27 | * @param motd MOTD that needs to be formatted 28 | * @return formatted MOTD 29 | */ 30 | String formatMotd(String motd, InetAddress ip); 31 | 32 | /** 33 | * Set the formatted motd in the users serverlist 34 | * @param e ping event 35 | * @param ip IP address of user 36 | */ 37 | void setServerlistMotd(ServerListPingEvent e, InetAddress ip); 38 | } 39 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/util/VaultIntegration.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.util; 2 | 3 | import org.bukkit.Bukkit; 4 | import org.bukkit.plugin.RegisteredServiceProvider; 5 | 6 | import net.milkbowl.vault.economy.Economy; 7 | 8 | public class VaultIntegration { 9 | 10 | private VaultIntegration() { 11 | throw new IllegalStateException("Utility class"); 12 | } 13 | 14 | public static Economy econ = null; 15 | 16 | public static void setupEconomy() { 17 | if (Bukkit.getPluginManager().getPlugin("Vault") == null) { 18 | Bukkit.getLogger().warning("[ServerlistMOTD] Couldn't find Vault. No %money%!"); 19 | return; 20 | } 21 | 22 | Bukkit.getLogger().info("[ServerlistMOTD] Hooking into Vault."); 23 | 24 | RegisteredServiceProvider rsp = Bukkit.getServer().getServicesManager().getRegistration(Economy.class); 25 | if (rsp == null) { 26 | Bukkit.getLogger().warning("[ServerlistMOTD] Couldn't find Economy-Plugin. No %money%!"); 27 | return; 28 | } 29 | econ = rsp.getProvider(); 30 | Bukkit.getLogger().info("[ServerlistMOTD] Using "+econ+" via Vault."); 31 | } 32 | 33 | public static Economy getEconomy() { 34 | return econ; 35 | } 36 | } -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/variables/WeatherVariable.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.variables; 2 | 3 | import org.bukkit.Bukkit; 4 | 5 | import cloud.bolte.serverlistmotd.SpigotConfig; 6 | 7 | /* 8 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 9 | * ServerlistMOTD is licensed under a 10 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 11 | * 12 | * You should have received a copy of the license along with this work. 13 | * If not, see . 14 | */ 15 | 16 | public class WeatherVariable { 17 | 18 | private WeatherVariable() { 19 | throw new IllegalStateException("Utility class"); 20 | } 21 | 22 | /** 23 | * Checks weather from world specified in config 24 | * @return rain/sun text from config 25 | */ 26 | public static String getWeather() { 27 | boolean thunder = Bukkit.getServer().getWorld(SpigotConfig.getWeatherWorld()).isThundering(); 28 | boolean rain = Bukkit.getServer().getWorld(SpigotConfig.getWeatherWorld()).hasStorm(); 29 | 30 | if (thunder || rain) { 31 | return SpigotConfig.getRainText(); 32 | } else { 33 | return SpigotConfig.getSunText(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/events/Ping.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.events; 2 | 3 | import java.net.InetAddress; 4 | 5 | import org.bukkit.Bukkit; 6 | import org.bukkit.event.EventHandler; 7 | import org.bukkit.event.Listener; 8 | import org.bukkit.event.server.ServerListPingEvent; 9 | 10 | import cloud.bolte.serverlistmotd.motd.MotdState; 11 | 12 | /* 13 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 14 | * ServerlistMOTD is licensed under a 15 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 16 | * 17 | * You should have received a copy of the license along with this work. 18 | * If not, see . 19 | */ 20 | 21 | public class Ping implements Listener { 22 | /* 23 | * Set motds according to config 24 | */ 25 | @EventHandler 26 | public void onPing(ServerListPingEvent e) { 27 | InetAddress ip = e.getAddress(); 28 | // Set standard motd 29 | MotdState.getInstance().getMotdBase().setServerlistMotd(e, ip); 30 | // Allow motd extension to overwrite motd 31 | if (MotdState.getInstance().getMotdExtension() != null) { 32 | MotdState.getInstance().getMotdExtension().setServerlistMotd(e, ip); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/events/IpLogging.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.events; 2 | 3 | import org.bukkit.event.EventHandler; 4 | import org.bukkit.event.Listener; 5 | import org.bukkit.event.player.AsyncPlayerPreLoginEvent; 6 | 7 | import cloud.bolte.serverlistmotd.Main; 8 | import cloud.bolte.serverlistmotd.util.IO; 9 | 10 | /* 11 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 12 | * ServerlistMOTD is licensed under a 13 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 14 | * 15 | * You should have received a copy of the license along with this work. 16 | * If not, see . 17 | */ 18 | 19 | public class IpLogging implements Listener{ 20 | @EventHandler 21 | public void onPreLogin(AsyncPlayerPreLoginEvent e) { 22 | //player not in hashmap 23 | if (!Main.IP_UUID.containsKey(e.getAddress())) { 24 | //player with different ip in hashmap 25 | if (IO.getKeyFromValue(Main.IP_UUID, e.getUniqueId()) != null) { 26 | //clear old entry and create one with new ip 27 | Main.IP_UUID.remove(IO.getKeyFromValue(Main.IP_UUID, e.getUniqueId())); 28 | } 29 | Main.IP_UUID.put(e.getAddress(), e.getUniqueId()); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/util/PapiIntegration.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.util; 2 | 3 | import org.bukkit.Bukkit; 4 | import org.bukkit.OfflinePlayer; 5 | 6 | import me.clip.placeholderapi.PlaceholderAPI; 7 | 8 | /* 9 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 10 | * ServerlistMOTD is licensed under a 11 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 12 | * 13 | * You should have received a copy of the license along with this work. 14 | * If not, see . 15 | */ 16 | 17 | public class PapiIntegration { 18 | private static boolean papiIsEnabled = false; 19 | 20 | private PapiIntegration() { 21 | throw new IllegalStateException("Utility class"); 22 | } 23 | 24 | public static void setupIntegration() { 25 | if (Bukkit.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI")) { 26 | Bukkit.getLogger().info("[ServerlistMOTD] Hooking into PlaceholderAPI."); 27 | papiIsEnabled = true; 28 | } 29 | } 30 | 31 | public static String replaceVariables(OfflinePlayer player, String motd) { 32 | if (papiIsEnabled) { 33 | return PlaceholderAPI.setPlaceholders(player, motd); 34 | } 35 | return motd; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/variables/MoneyVariable.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.variables; 2 | 3 | import java.net.InetAddress; 4 | 5 | import org.bukkit.Bukkit; 6 | import org.bukkit.OfflinePlayer; 7 | 8 | import cloud.bolte.serverlistmotd.Main; 9 | import cloud.bolte.serverlistmotd.util.VaultIntegration; 10 | 11 | /* 12 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 13 | * ServerlistMOTD is licensed under a 14 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 15 | * 16 | * You should have received a copy of the license along with this work. 17 | * If not, see . 18 | */ 19 | 20 | public class MoneyVariable { 21 | 22 | private MoneyVariable() { 23 | throw new IllegalStateException("Utility class"); 24 | } 25 | 26 | /** 27 | * Get balance from player. Vault and a economy plugin has 28 | * to be installed on the server. 29 | * @param ip IP from known player 30 | * @return balance 31 | */ 32 | public static Double getMoney(InetAddress ip) { 33 | try { 34 | OfflinePlayer p = Bukkit.getOfflinePlayer(Main.IP_UUID.get(ip)); 35 | if (p.hasPlayedBefore()) { 36 | return VaultIntegration.getEconomy().getBalance(p); 37 | }else { 38 | //User is uncached by Spigot 39 | //p is null 40 | return 0d; 41 | } 42 | } catch (NullPointerException npe) { 43 | return -1d; 44 | } catch (NoClassDefFoundError nc) { 45 | return 0d; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/variables/PlayerVariable.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.variables; 2 | 3 | import java.net.InetAddress; 4 | 5 | import org.bukkit.Bukkit; 6 | import org.bukkit.OfflinePlayer; 7 | 8 | import cloud.bolte.serverlistmotd.Main; 9 | 10 | /* 11 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 12 | * ServerlistMOTD is licensed under a 13 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 14 | * 15 | * You should have received a copy of the license along with this work. 16 | * If not, see . 17 | */ 18 | 19 | public class PlayerVariable { 20 | 21 | private PlayerVariable() { 22 | throw new IllegalStateException("Utility class"); 23 | } 24 | 25 | /** 26 | * Checks if IP is known in HashMap IP_UUID 27 | * @param ip IP from player 28 | * @return true/false if known 29 | */ 30 | public static boolean isKnownPlayer(InetAddress ip) { 31 | return Main.IP_UUID.containsKey(ip); 32 | } 33 | 34 | /** 35 | * Caution: Doesn't check if ip is recorded in HashMap. 36 | * Use isKnownPlayer beforehand! (NPE!) 37 | * @param ip IP from known player 38 | * @return Name from player 39 | */ 40 | public static String getNameFromIP(InetAddress ip) { 41 | try { 42 | OfflinePlayer p = Bukkit.getOfflinePlayer(Main.IP_UUID.get(ip)); 43 | if (p.hasPlayedBefore()) { 44 | return p.getName(); 45 | }else { 46 | //User is uncached by Spigot 47 | return ""; 48 | } 49 | } catch(NullPointerException npe) { 50 | return ""; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/slots/FakeOnlinePlayer.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.slots; 2 | 3 | import java.util.Random; 4 | 5 | import com.comphenix.protocol.wrappers.WrappedServerPing; 6 | 7 | import static cloud.bolte.serverlistmotd.SpigotConfig.fakeOnlinePlayerRandomNumberEnabled; 8 | import static cloud.bolte.serverlistmotd.SpigotConfig.getfakeOnlinePlayerRandomNumberMax; 9 | import static cloud.bolte.serverlistmotd.SpigotConfig.getfakeOnlinePlayerRandomNumberMin; 10 | import static cloud.bolte.serverlistmotd.SpigotConfig.getFakeOnlinePlayerNumber; 11 | 12 | /* 13 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 14 | * ServerlistMOTD is licensed under a 15 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 16 | * 17 | * You should have received a copy of the license along with this work. 18 | * If not, see . 19 | */ 20 | 21 | public class FakeOnlinePlayer { 22 | 23 | private FakeOnlinePlayer() { 24 | throw new IllegalStateException("Utility class"); 25 | } 26 | 27 | /** 28 | * Activate the FakeOnlinePlayer feature which fakes the online 29 | * player count in the serverlist. 30 | * @param ping object from ProtocolLib 31 | */ 32 | public static void activateFakeOnlinePlayer(WrappedServerPing ping) { 33 | if (!fakeOnlinePlayerRandomNumberEnabled()) { 34 | ping.setPlayersOnline(getFakeOnlinePlayerNumber()); 35 | } else { 36 | Random random = new Random(); 37 | ping.setPlayersOnline(random.nextInt(getfakeOnlinePlayerRandomNumberMax()+1 - getfakeOnlinePlayerRandomNumberMin()) 38 | + getfakeOnlinePlayerRandomNumberMin()); 39 | } 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/slots/OnlineMultiplier.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.slots; 2 | 3 | import org.bukkit.Bukkit; 4 | 5 | import com.comphenix.protocol.wrappers.WrappedServerPing; 6 | 7 | import static cloud.bolte.serverlistmotd.SpigotConfig.getOnlineMultiplier; 8 | import static cloud.bolte.serverlistmotd.SpigotConfig.getOnlineMultiplierMinSlots; 9 | import static cloud.bolte.serverlistmotd.SpigotConfig.getOnlineMultiplierMaxSlots; 10 | import static cloud.bolte.serverlistmotd.SpigotConfig.getOnlineMultiplierAddSlots; 11 | 12 | /* 13 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 14 | * ServerlistMOTD is licensed under a 15 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 16 | * 17 | * You should have received a copy of the license along with this work. 18 | * If not, see . 19 | */ 20 | 21 | public class OnlineMultiplier { 22 | 23 | private OnlineMultiplier() { 24 | throw new IllegalStateException("Utility class"); 25 | } 26 | 27 | /** 28 | * Set slots and online players according to OnlineMultiplier settings in config. 29 | * @param ping Ping object from ProtocolLib 30 | */ 31 | public static void activateOnlineMultiplier(WrappedServerPing ping) { 32 | int multipliedOnlinePlayer = (int) Math.round(Bukkit.getOnlinePlayers().size() * getOnlineMultiplier()); 33 | 34 | if (multipliedOnlinePlayer >= getOnlineMultiplierMinSlots()) { 35 | ping.setPlayersMaximum(multipliedOnlinePlayer + getOnlineMultiplierAddSlots()); 36 | ping.setPlayersOnline(multipliedOnlinePlayer); 37 | } else { 38 | ping.setPlayersOnline(multipliedOnlinePlayer); 39 | ping.setPlayersMaximum(getOnlineMultiplierMinSlots()); 40 | } 41 | 42 | if (multipliedOnlinePlayer >= getOnlineMultiplierMaxSlots()) { 43 | ping.setPlayersMaximum(getOnlineMultiplierMaxSlots()); 44 | ping.setPlayersOnline(getOnlineMultiplierMaxSlots()); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/slots/SlotsPlusOne.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.slots; 2 | 3 | import org.bukkit.Bukkit; 4 | 5 | import com.comphenix.protocol.wrappers.WrappedServerPing; 6 | 7 | import cloud.bolte.serverlistmotd.SpigotConfig; 8 | 9 | /* 10 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 11 | * ServerlistMOTD is licensed under a 12 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 13 | * 14 | * You should have received a copy of the license along with this work. 15 | * If not, see . 16 | */ 17 | 18 | public class SlotsPlusOne { 19 | 20 | private SlotsPlusOne() { 21 | throw new IllegalStateException("Utility class"); 22 | } 23 | 24 | /** 25 | * Set slots and online players according to SlotsPlusOne settings in config. 26 | * @param ping Ping object from ProtocolLib 27 | */ 28 | public static void acitvateSlotsPlusOne(WrappedServerPing ping) { 29 | int onlinenumber = Bukkit.getOnlinePlayers().size(); 30 | 31 | if (onlinenumber >= SpigotConfig.getSlotsPlusOneMinSlots()) { 32 | ping.setPlayersMaximum(onlinenumber + SpigotConfig.getSlotsPlusOneAddSlotsToOnline()); 33 | } else { 34 | ping.setPlayersMaximum(SpigotConfig.getSlotsPlusOneMinSlots()); 35 | } 36 | 37 | if (onlinenumber == SpigotConfig.getSlotsPlusOneMaxSlots()) { 38 | ping.setPlayersMaximum(SpigotConfig.getSlotsPlusOneMaxSlots()); 39 | } 40 | } 41 | 42 | /** 43 | * Get a SlotsPlusOne value for further usage 44 | * @return SlotsPlusOne value 45 | */ 46 | public static int getSlotsPlusOneValue() { 47 | int onlinenumber = Bukkit.getOnlinePlayers().size(); 48 | 49 | if (onlinenumber >= SpigotConfig.getSlotsPlusOneMinSlots()) { 50 | return onlinenumber + SpigotConfig.getSlotsPlusOneAddSlotsToOnline(); 51 | } else if (onlinenumber == SpigotConfig.getSlotsPlusOneMaxSlots()) { 52 | return SpigotConfig.getSlotsPlusOneMaxSlots(); 53 | } else { 54 | return SpigotConfig.getSlotsPlusOneMinSlots(); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/slots/OutdatedClientText.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.slots; 2 | 3 | import org.bukkit.Bukkit; 4 | import org.bukkit.ChatColor; 5 | 6 | import com.comphenix.protocol.wrappers.WrappedServerPing; 7 | 8 | import cloud.bolte.serverlistmotd.SpigotConfig; 9 | import cloud.bolte.serverlistmotd.util.PapiIntegration; 10 | import cloud.bolte.serverlistmotd.variables.RandomNumberVariable; 11 | 12 | /* 13 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 14 | * ServerlistMOTD is licensed under a 15 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 16 | * 17 | * You should have received a copy of the license along with this work. 18 | * If not, see . 19 | */ 20 | 21 | public class OutdatedClientText { 22 | 23 | private OutdatedClientText() { 24 | throw new IllegalStateException("Utility class"); 25 | } 26 | 27 | /** 28 | * Set custom protocol version name with config text 29 | * Triggered when outdated client pings 30 | * @param ping WrappedServerPing from ProtcolLib 31 | */ 32 | public static void activate(WrappedServerPing ping) { 33 | ping.setVersionName(formatText(SpigotConfig.getOudatedClientText())); 34 | } 35 | 36 | /** 37 | * @param versionText unformatted version text 38 | * @return formatted version text (vars, color) 39 | */ 40 | private static String formatText(String versionText) { 41 | String realslots = Bukkit.getServer().getMaxPlayers()+""; 42 | String realonline = Bukkit.getServer().getOnlinePlayers().size()+""; 43 | String fakeslots = SpigotConfig.getFakeMaxPlayerNumber()+""; 44 | String fakeonline = SpigotConfig.getFakeOnlinePlayerNumber()+""; 45 | 46 | String formatted = ChatColor.translateAlternateColorCodes('&', versionText) 47 | .replace("%realslots%", realslots) 48 | .replace("%realonline%", realonline) 49 | .replace("%fakeonline%", fakeonline) 50 | .replace("%fakeslots%", fakeslots) 51 | .replace("%slotsplusone%", SlotsPlusOne.getSlotsPlusOneValue()+"") 52 | .replace("%randomnumber%", RandomNumberVariable.getRandomNumber()+""); 53 | formatted = PapiIntegration.replaceVariables(null, formatted); 54 | return formatted; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/slots/HoverText.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.slots; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.UUID; 6 | 7 | import org.bukkit.ChatColor; 8 | 9 | import com.comphenix.protocol.wrappers.WrappedGameProfile; 10 | import com.comphenix.protocol.wrappers.WrappedServerPing; 11 | 12 | import cloud.bolte.serverlistmotd.Main; 13 | import cloud.bolte.serverlistmotd.SpigotConfig; 14 | import cloud.bolte.serverlistmotd.util.PapiIntegration; 15 | import cloud.bolte.serverlistmotd.variables.RandomPlayerVariable; 16 | import cloud.bolte.serverlistmotd.variables.TimeVariable; 17 | import cloud.bolte.serverlistmotd.variables.WeatherVariable; 18 | 19 | /* 20 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 21 | * ServerlistMOTD is licensed under a 22 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 23 | * 24 | * You should have received a copy of the license along with this work. 25 | * If not, see . 26 | */ 27 | 28 | public class HoverText { 29 | 30 | private HoverText() { 31 | throw new IllegalStateException("Utility class"); 32 | } 33 | 34 | /** 35 | * Create custom GameProfile and therefore activate HoverText with custom text 36 | * @param ping WrappedServerPing from ProtocolLib 37 | */ 38 | public static void activateHoverText(WrappedServerPing ping) { 39 | List players = new ArrayList<>(); 40 | for (String string : SpigotConfig.getHoverText()) { 41 | players.add(new WrappedGameProfile(UUID.randomUUID(), formatText(string))); 42 | } 43 | ping.setPlayers(players); 44 | } 45 | 46 | /** 47 | * @param hoverLine unformatted HoverText set in config 48 | * @return formatted HoverText (color, var) 49 | */ 50 | private static String formatText(String hoverLine) { 51 | String formatted = ChatColor.translateAlternateColorCodes('&', hoverLine) 52 | .replace("%weather%", WeatherVariable.getWeather()) 53 | .replace("%time%", TimeVariable.getTime()) 54 | .replace("%randomplayer%", RandomPlayerVariable.getRandomPlayer()) 55 | .replace("%line%", "\n"); 56 | formatted = PapiIntegration.replaceVariables(null, formatted); 57 | return formatted; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/variables/RandomPlayerVariable.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.variables; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Random; 5 | import java.util.UUID; 6 | 7 | import org.bukkit.Bukkit; 8 | import org.bukkit.OfflinePlayer; 9 | import org.bukkit.entity.Player; 10 | 11 | import cloud.bolte.serverlistmotd.Main; 12 | import cloud.bolte.serverlistmotd.SpigotConfig; 13 | 14 | /* 15 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 16 | * ServerlistMOTD is licensed under a 17 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 18 | * 19 | * You should have received a copy of the license along with this work. 20 | * If not, see . 21 | */ 22 | 23 | public class RandomPlayerVariable { 24 | private final static Random random = new Random(); 25 | 26 | private RandomPlayerVariable() { 27 | throw new IllegalStateException("Utility class"); 28 | } 29 | 30 | /** 31 | * Get random player name from online players 32 | * @return random player name 33 | */ 34 | public static String getRandomPlayer() { 35 | if (Bukkit.getOnlinePlayers().size() > 0) { 36 | Player player = (Player) Bukkit.getOnlinePlayers().toArray() 37 | [random.nextInt(Bukkit.getOnlinePlayers().size())]; 38 | return player.getName(); 39 | } else { 40 | return getRandomOfflinePlayer(); 41 | } 42 | } 43 | 44 | /** 45 | * Get random player name from IP_UUID hashmap 46 | * @return random player name 47 | */ 48 | private static String getRandomOfflinePlayer() { 49 | if (!(Main.IP_UUID.isEmpty())) { 50 | ArrayList values = new ArrayList<>(Main.IP_UUID.values()); 51 | int index = random.nextInt(values.size()); 52 | if (SpigotConfig.randomPlayerVariableUseTextEnabled()) { 53 | return SpigotConfig.getRandomPlayerVariableText(); 54 | } else { 55 | OfflinePlayer p = Bukkit.getOfflinePlayer(values.get(index)); 56 | if (p.hasPlayedBefore()) { 57 | return p.getName(); 58 | }else { 59 | //User is uncached by Spigot 60 | //p is null 61 | return ""; 62 | } 63 | } 64 | } else { 65 | //No player joined before 66 | //Just returning my name ;-) 67 | return "Strumswell"; 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/ban/BanInterface.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.ban; 2 | 3 | /* 4 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 5 | * ServerlistMOTD is licensed under a 6 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 7 | * 8 | * You should have received a copy of the license along with this work. 9 | * If not, see . 10 | */ 11 | 12 | // TODO: Migrate to UUID 13 | public interface BanInterface { 14 | 15 | /** 16 | * @param playerName Players username 17 | * @return Ban reason 18 | */ 19 | String banReason(String playerName); 20 | 21 | /** 22 | * @param playerName 23 | * @return Expiration date 24 | */ 25 | Long expires(String playerName); 26 | 27 | /** 28 | * @param playerName 29 | * @return Seconds of expiration date 30 | */ 31 | String banExpDateSec(String playerName); 32 | 33 | /** 34 | * @param playerName 35 | * @return Minutes of expiration date 36 | */ 37 | String banExpDateMin(String playerName); 38 | 39 | /** 40 | * @param playerName 41 | * @return Hours of expiration date 42 | */ 43 | String banExpDateHour(String playerName); 44 | 45 | /** 46 | * @param playerName 47 | * @return Day of expiration date 48 | */ 49 | String banExpDateDay(String playerName); 50 | 51 | /** 52 | * @param playerName 53 | * @return Month of expiration date 54 | */ 55 | String banExpDateMonth(String playerName); 56 | 57 | /** 58 | * @param playerName 59 | * @return Year of expiration date 60 | */ 61 | String banExpDateYear(String playerName); 62 | 63 | /** 64 | * @param playerName 65 | * @return Returns the date 66 | */ 67 | String date(String playerName); 68 | 69 | /** 70 | * @param playerName 71 | * @return Returns the time 72 | */ 73 | String time(String playerName); 74 | 75 | /** 76 | * @param playerName 77 | * @return Returns the actor 78 | */ 79 | String banActor(String playerName); 80 | 81 | /** 82 | * @param playerName 83 | * @return Returns when the ban was created 84 | */ 85 | String banCreated(String playerName); 86 | 87 | /** 88 | * @param playerName 89 | * @return This method returns a unique ID belonging to a ban 90 | */ 91 | String banID(String playerName); 92 | } 93 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/slots/VersionText.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.slots; 2 | 3 | import org.bukkit.Bukkit; 4 | import org.bukkit.ChatColor; 5 | 6 | import com.comphenix.protocol.wrappers.WrappedServerPing; 7 | 8 | import cloud.bolte.serverlistmotd.SpigotConfig; 9 | import cloud.bolte.serverlistmotd.util.PapiIntegration; 10 | import cloud.bolte.serverlistmotd.variables.RandomNumberVariable; 11 | 12 | /* 13 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 14 | * ServerlistMOTD is licensed under a 15 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 16 | * 17 | * You should have received a copy of the license along with this work. 18 | * If not, see . 19 | */ 20 | 21 | public class VersionText { 22 | 23 | private VersionText() { 24 | throw new IllegalStateException("Utility class"); 25 | } 26 | 27 | //Interesting: When VersionName set to null server doesn't respond -> RestrictedMode? 28 | /** 29 | * Set custom protocol version and name with config text 30 | * @param ping WrappedServerPing from ProtcolLib 31 | */ 32 | public static void activateVersionText(WrappedServerPing ping) { 33 | ping.setVersionProtocol(-1); 34 | ping.setVersionName(formatText(SpigotConfig.getVersionText())); 35 | } 36 | 37 | /** 38 | * @param versionText unformatted version text 39 | * @return formatted version text (vars, color) 40 | */ 41 | private static String formatText(String versionText) { 42 | String realslots = Bukkit.getServer().getMaxPlayers()+""; 43 | String realonline = Bukkit.getServer().getOnlinePlayers().size()+""; 44 | String fakeslots = SpigotConfig.getFakeMaxPlayerNumber()+""; 45 | String fakeonline = SpigotConfig.getFakeOnlinePlayerNumber()+""; 46 | 47 | String formatted = ChatColor.translateAlternateColorCodes('&', versionText) 48 | .replace("%realslots%", realslots) 49 | .replace("%realonline%", realonline) 50 | .replace("%fakeonline%", fakeonline) 51 | .replace("%fakeslots%", fakeslots) 52 | .replace("%slotsplusone%", SlotsPlusOne.getSlotsPlusOneValue()+"") 53 | .replace("%randomnumber%", RandomNumberVariable.getRandomNumber()+""); 54 | formatted = PapiIntegration.replaceVariables(null, formatted); 55 | return formatted; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/motd/MotdState.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.motd; 2 | 3 | import org.bukkit.Bukkit; 4 | 5 | import cloud.bolte.serverlistmotd.SpigotConfig; 6 | 7 | /* 8 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 9 | * ServerlistMOTD is licensed under a 10 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 11 | * 12 | * You should have received a copy of the license along with this work. 13 | * If not, see . 14 | */ 15 | 16 | public class MotdState { 17 | 18 | private Motd motdBase; 19 | private Motd motdExtension; 20 | private static MotdState instance; 21 | 22 | /** 23 | * Initialize motds on object creation 24 | */ 25 | private MotdState() { 26 | initializeMotds(); 27 | } 28 | 29 | /** 30 | * Use to get access to object of class 31 | * @return singleton object of class 32 | */ 33 | public static MotdState getInstance() { 34 | if (MotdState.instance == null) { 35 | MotdState.instance = new MotdState(); 36 | } 37 | return MotdState.instance; 38 | } 39 | 40 | /** 41 | * Use to get activated basic motd 42 | * @return basic motd (e.g. STANDARD) 43 | */ 44 | public Motd getMotdBase() { 45 | return motdBase; 46 | } 47 | 48 | /** 49 | * Use to get activated motd extensions 50 | * @return extions motd (e.g. BAN) 51 | */ 52 | public Motd getMotdExtension() { 53 | return motdExtension; 54 | } 55 | 56 | /** 57 | * Checks the config and sets the enabled motd(-extentsion) 58 | * Very important to use it on config reload! 59 | */ 60 | public void initializeMotds() { 61 | if (SpigotConfig.randomMotdEnabled()) { 62 | motdBase = new RandomMotd(); 63 | } else { 64 | motdBase = new ClassicMotd(); 65 | } 66 | 67 | //From lowest priority to highest! 68 | motdExtension = null; 69 | if (SpigotConfig.banMotdEnabled()) 70 | motdExtension = new BanMotd(); 71 | if (SpigotConfig.banMotdEnabled() && Bukkit.getServer().getPluginManager().getPlugin("MaxBans") != null) 72 | motdExtension = new MaxBansMotd(); 73 | if (SpigotConfig.banMotdEnabled() && Bukkit.getServer().getPluginManager().getPlugin("BanManager") != null) 74 | motdExtension = new BanManagerMotd(); 75 | if (SpigotConfig.whitelistMotdEnabled()) 76 | motdExtension = new WhitelistMotd(); 77 | if (SpigotConfig.restrictedModeEnabled()) 78 | motdExtension = new RestrictedModeMotd(); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/motd/ClassicMotd.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.motd; 2 | 3 | import java.net.InetAddress; 4 | 5 | import cloud.bolte.serverlistmotd.util.HexResolver; 6 | import org.bukkit.Bukkit; 7 | import org.bukkit.ChatColor; 8 | import org.bukkit.event.server.ServerListPingEvent; 9 | 10 | import cloud.bolte.serverlistmotd.Main; 11 | import cloud.bolte.serverlistmotd.SpigotConfig; 12 | import cloud.bolte.serverlistmotd.util.PapiIntegration; 13 | import cloud.bolte.serverlistmotd.variables.MoneyVariable; 14 | import cloud.bolte.serverlistmotd.variables.PlayerVariable; 15 | import cloud.bolte.serverlistmotd.variables.RandomPlayerVariable; 16 | import cloud.bolte.serverlistmotd.variables.TimeVariable; 17 | import cloud.bolte.serverlistmotd.variables.WeatherVariable; 18 | 19 | /* 20 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 21 | * ServerlistMOTD is licensed under a 22 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 23 | * 24 | * You should have received a copy of the license along with this work. 25 | * If not, see . 26 | */ 27 | 28 | public class ClassicMotd implements Motd{ 29 | 30 | @Override 31 | public String getMOTD(InetAddress ip) { 32 | if (Main.IP_UUID.containsKey(ip)) { 33 | return SpigotConfig.getRegularsMotd(); 34 | } else return SpigotConfig.getNewbieMotd(); 35 | } 36 | 37 | @Override 38 | public String formatMotd(String motd, InetAddress ip) { 39 | String formattedMotd; 40 | formattedMotd = ChatColor.translateAlternateColorCodes('&', motd) 41 | .replace("%line%", "\n") 42 | .replace("%weather%", WeatherVariable.getWeather()) 43 | .replace("%time%", TimeVariable.getTime()) 44 | .replace("%randomplayer%", RandomPlayerVariable.getRandomPlayer()); 45 | 46 | try { 47 | if (PlayerVariable.isKnownPlayer(ip)) { 48 | formattedMotd = formattedMotd 49 | .replace("%player%", PlayerVariable.getNameFromIP(ip)) 50 | .replace("%money%", MoneyVariable.getMoney(ip)+""); 51 | formattedMotd = PapiIntegration.replaceVariables(Bukkit.getOfflinePlayer(Main.IP_UUID.get(ip)), formattedMotd); 52 | } else { 53 | formattedMotd = PapiIntegration.replaceVariables(null, formattedMotd); 54 | } 55 | } catch(NullPointerException npe) { } 56 | 57 | formattedMotd = HexResolver.parseHexString(formattedMotd); 58 | return formattedMotd; 59 | } 60 | 61 | public void setServerlistMotd(ServerListPingEvent e, InetAddress ip) { 62 | e.setMotd(formatMotd(getMOTD(ip), ip)); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/motd/RandomMotd.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.motd; 2 | 3 | import java.net.InetAddress; 4 | import java.util.List; 5 | import java.util.Random; 6 | 7 | import cloud.bolte.serverlistmotd.util.HexResolver; 8 | import org.bukkit.Bukkit; 9 | import org.bukkit.ChatColor; 10 | import org.bukkit.event.server.ServerListPingEvent; 11 | 12 | import cloud.bolte.serverlistmotd.Main; 13 | import cloud.bolte.serverlistmotd.SpigotConfig; 14 | import cloud.bolte.serverlistmotd.util.PapiIntegration; 15 | import cloud.bolte.serverlistmotd.variables.MoneyVariable; 16 | import cloud.bolte.serverlistmotd.variables.PlayerVariable; 17 | import cloud.bolte.serverlistmotd.variables.RandomPlayerVariable; 18 | import cloud.bolte.serverlistmotd.variables.TimeVariable; 19 | import cloud.bolte.serverlistmotd.variables.WeatherVariable; 20 | 21 | /* 22 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 23 | * ServerlistMOTD is licensed under a 24 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 25 | * 26 | * You should have received a copy of the license along with this work. 27 | * If not, see . 28 | */ 29 | 30 | public class RandomMotd implements Motd { 31 | private final Random random = new Random(); 32 | 33 | @Override 34 | public String getMOTD(InetAddress ip) { 35 | List motds; 36 | if (Main.IP_UUID.containsKey(ip)) { 37 | motds = SpigotConfig.getRegularsRandomMotd(); 38 | } else { 39 | motds = SpigotConfig.getNewbieRandomMotd(); 40 | } 41 | return motds.get(this.random.nextInt(motds.size())); 42 | } 43 | 44 | @Override 45 | public String formatMotd(String motd, InetAddress ip) { 46 | String formattedMotd = ChatColor.translateAlternateColorCodes('&', motd) 47 | .replace("%line%", "\n") 48 | .replace("%weather%", WeatherVariable.getWeather()) 49 | .replace("%time%", TimeVariable.getTime()) 50 | .replace("%randomplayer%", RandomPlayerVariable.getRandomPlayer()); 51 | 52 | if (PlayerVariable.isKnownPlayer(ip)) { 53 | formattedMotd = formattedMotd 54 | .replace("%player%", PlayerVariable.getNameFromIP(ip) 55 | .replace("%money%", MoneyVariable.getMoney(ip)+"")); 56 | formattedMotd = PapiIntegration.replaceVariables(Bukkit.getOfflinePlayer(Main.IP_UUID.get(ip)), formattedMotd); 57 | } else { 58 | formattedMotd = PapiIntegration.replaceVariables(null, formattedMotd); 59 | } 60 | formattedMotd = HexResolver.parseHexString(formattedMotd); 61 | return formattedMotd; 62 | } 63 | 64 | public void setServerlistMotd(ServerListPingEvent e, InetAddress ip) { 65 | e.setMotd(formatMotd(getMOTD(ip), ip)); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/motd/RestrictedModeMotd.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.motd; 2 | 3 | import java.net.InetAddress; 4 | 5 | import cloud.bolte.serverlistmotd.util.HexResolver; 6 | import org.bukkit.Bukkit; 7 | import org.bukkit.ChatColor; 8 | import org.bukkit.OfflinePlayer; 9 | import org.bukkit.event.server.ServerListPingEvent; 10 | 11 | import cloud.bolte.serverlistmotd.Main; 12 | import cloud.bolte.serverlistmotd.SpigotConfig; 13 | import cloud.bolte.serverlistmotd.util.PapiIntegration; 14 | import cloud.bolte.serverlistmotd.variables.MoneyVariable; 15 | import cloud.bolte.serverlistmotd.variables.PlayerVariable; 16 | import cloud.bolte.serverlistmotd.variables.RandomPlayerVariable; 17 | import cloud.bolte.serverlistmotd.variables.TimeVariable; 18 | import cloud.bolte.serverlistmotd.variables.WeatherVariable; 19 | 20 | /* 21 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 22 | * ServerlistMOTD is licensed under a 23 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 24 | * 25 | * You should have received a copy of the license along with this work. 26 | * If not, see . 27 | */ 28 | 29 | public class RestrictedModeMotd implements Motd { 30 | 31 | @Override 32 | public String getMOTD(InetAddress ip) { 33 | if (Main.IP_UUID.containsKey(ip)) { 34 | OfflinePlayer p = Bukkit.getOfflinePlayer(Main.IP_UUID.get(ip)); 35 | if (p.isOp()) { 36 | return SpigotConfig.getRestrictedAccessGrantedMotd(); 37 | } else return SpigotConfig.getRestrictedAccessDeniedMotd(); 38 | } else return SpigotConfig.getRestrictedAccessDeniedMotd(); 39 | } 40 | 41 | @Override 42 | public String formatMotd(String motd, InetAddress ip) { 43 | String formattedMotd = ChatColor.translateAlternateColorCodes('&', motd) 44 | .replace("%line%", "\n") 45 | .replace("%weather%", WeatherVariable.getWeather()) 46 | .replace("%time%", TimeVariable.getTime()) 47 | .replace("%randomplayer%", RandomPlayerVariable.getRandomPlayer()); 48 | 49 | if (PlayerVariable.isKnownPlayer(ip)) { 50 | formattedMotd = formattedMotd 51 | .replace("%player%", PlayerVariable.getNameFromIP(ip)) 52 | .replace("%money%", MoneyVariable.getMoney(ip)+""); 53 | formattedMotd = PapiIntegration.replaceVariables(Bukkit.getOfflinePlayer(Main.IP_UUID.get(ip)), formattedMotd); 54 | } else { 55 | formattedMotd = PapiIntegration.replaceVariables(null, formattedMotd); 56 | } 57 | formattedMotd = HexResolver.parseHexString(formattedMotd); 58 | return formattedMotd; 59 | } 60 | 61 | /** 62 | * Sets RestrictedMode motd according to if server knows player, 63 | * formats and sets it and kicks players without perms. 64 | * 65 | * @param e ServerlistPingEvent from Spigot 66 | * @param ip IP of pinging player 67 | */ 68 | public void setServerlistMotd(ServerListPingEvent e, InetAddress ip) { 69 | e.setMotd(formatMotd(getMOTD(ip), ip)); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/motd/WhitelistMotd.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.motd; 2 | 3 | import java.net.InetAddress; 4 | 5 | import cloud.bolte.serverlistmotd.util.HexResolver; 6 | import org.bukkit.Bukkit; 7 | import org.bukkit.ChatColor; 8 | import org.bukkit.OfflinePlayer; 9 | import org.bukkit.event.server.ServerListPingEvent; 10 | 11 | import cloud.bolte.serverlistmotd.Main; 12 | import cloud.bolte.serverlistmotd.SpigotConfig; 13 | import cloud.bolte.serverlistmotd.util.PapiIntegration; 14 | import cloud.bolte.serverlistmotd.variables.MoneyVariable; 15 | import cloud.bolte.serverlistmotd.variables.PlayerVariable; 16 | import cloud.bolte.serverlistmotd.variables.RandomPlayerVariable; 17 | import cloud.bolte.serverlistmotd.variables.TimeVariable; 18 | import cloud.bolte.serverlistmotd.variables.WeatherVariable; 19 | 20 | /* 21 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 22 | * ServerlistMOTD is licensed under a 23 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 24 | * 25 | * You should have received a copy of the license along with this work. 26 | * If not, see . 27 | */ 28 | 29 | public class WhitelistMotd implements Motd { 30 | 31 | @Override 32 | public String getMOTD(InetAddress ip) { 33 | OfflinePlayer p = Bukkit.getOfflinePlayer(Main.IP_UUID.get(ip)); 34 | if (Bukkit.getWhitelistedPlayers().contains(p) || p.isOp()) { 35 | return SpigotConfig.getWhitelistMotd(); 36 | } else return SpigotConfig.getNotWhitelistedMotd(); 37 | } 38 | 39 | @Override 40 | public String formatMotd(String motd, InetAddress ip) { 41 | String formattedMotd = ChatColor.translateAlternateColorCodes('&', motd) 42 | .replace("%line%", "\n") 43 | .replace("%randomplayer%", RandomPlayerVariable.getRandomPlayer()) 44 | .replace("%weather%", WeatherVariable.getWeather()) 45 | .replace("%time%", TimeVariable.getTime()); 46 | 47 | if (PlayerVariable.isKnownPlayer(ip)) { 48 | formattedMotd = formattedMotd 49 | .replace("%player%", PlayerVariable.getNameFromIP(ip)) 50 | .replace("%money%", MoneyVariable.getMoney(ip)+""); 51 | formattedMotd = PapiIntegration.replaceVariables(Bukkit.getOfflinePlayer(Main.IP_UUID.get(ip)), formattedMotd); 52 | } else { 53 | formattedMotd = PapiIntegration.replaceVariables(null, formattedMotd); 54 | } 55 | formattedMotd = HexResolver.parseHexString(formattedMotd); 56 | return formattedMotd; 57 | } 58 | 59 | /** 60 | * Sets WhitelistMotd according to if server knows player, 61 | * formats and sets it. 62 | * 63 | * @param e ServerlistPingEvent from Spigot 64 | * @param ip IP of pinging player 65 | */ 66 | public void setServerlistMotd(ServerListPingEvent e, InetAddress ip) { 67 | if (Bukkit.hasWhitelist()) { 68 | if (Main.IP_UUID.containsKey(ip)) { 69 | e.setMotd(formatMotd(getMOTD(ip), ip)); 70 | } else e.setMotd(formatMotd(SpigotConfig.getNotWhitelistedMotd(), ip)); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/util/Gradient.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.util; 2 | 3 | import java.awt.Color; 4 | import java.util.List; 5 | 6 | /** 7 | * Author: https://github.com/harry0198/HexiTextLib MIT License 8 | * 9 | * NOTICE FROM harry0198: 10 | * ------------------------- 11 | * Gradient class 12 | * Derived from: 13 | * https://github.com/Rosewood-Development/RoseStacker/blob/master/Plugin/src/main/java/dev/rosewood/rosestacker/utils/HexUtils.java 14 | * https://github.com/Oribuin/ChatEmojis/blob/master/src/main/java/xyz/oribuin/chatemojis/utils/HexUtils.java 15 | * 16 | * Unsure who original author is. 17 | * @author unknown 18 | */ 19 | public class Gradient { 20 | 21 | private final List colors; 22 | private final int stepSize; 23 | private int step, stepIndex; 24 | 25 | public Gradient(List colors, int totalColors) { 26 | if (colors.size() < 2) 27 | throw new IllegalArgumentException("Please provide at least 2 colors, e.g. "); 28 | 29 | if (totalColors < 1) 30 | throw new IllegalArgumentException("Must have at least 1 total color"); 31 | 32 | this.colors = colors; 33 | this.stepSize = totalColors / (colors.size() - 1); 34 | this.step = this.stepIndex = 0; 35 | } 36 | 37 | /** 38 | * @return the next color in the gradient 39 | */ 40 | public Color next() { 41 | 42 | Color color; 43 | if (this.stepIndex + 1 < this.colors.size()) { 44 | Color start = this.colors.get(this.stepIndex); 45 | Color end = this.colors.get(this.stepIndex + 1); 46 | float interval = (float) this.step / this.stepSize; 47 | 48 | color = getGradientInterval(start, end, interval); 49 | } else { 50 | color = this.colors.get(this.colors.size() - 1); 51 | } 52 | 53 | this.step += 1; 54 | if (this.step >= this.stepSize) { 55 | this.step = 0; 56 | this.stepIndex++; 57 | } 58 | 59 | return color; 60 | } 61 | 62 | /** 63 | * Gets a color along a linear gradient between two colors 64 | * 65 | * @param start The start color 66 | * @param end The end color 67 | * @param interval The interval to get, between 0 and 1 inclusively 68 | * @return A Color at the interval between the start and end colors 69 | */ 70 | public static Color getGradientInterval(Color start, Color end, float interval) { 71 | if (0 > interval || interval > 1) 72 | throw new IllegalArgumentException("Interval must be between 0 and 1 inclusively."); 73 | 74 | int r = (int) (end.getRed() * interval + start.getRed() * (1 - interval)); 75 | int g = (int) (end.getGreen() * interval + start.getGreen() * (1 - interval)); 76 | int b = (int) (end.getBlue() * interval + start.getBlue() * (1 - interval)); 77 | 78 | return new Color(r, g, b); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ServerlistMOTD X 2 | 3 | ### Download newest Release: [![](https://img.shields.io/github/downloads/strumswell/ServerlistMOTD-X/X-2021-11-23/total)](https://github.com/strumswell/ServerlistMOTD-X/releases/download/X-2021-11-23/ServerlistMOTD.jar) 4 | 5 | ### Download last Release: [![](https://img.shields.io/github/downloads/strumswell/ServerlistMOTD-X/X-2020-09-05/total)](https://github.com/strumswell/ServerlistMOTD-X/releases/download/X-2020-09-05/ServerlistMOTD.jar) 6 | 7 | ### Dependencies 8 | 9 | - ProtocolLib (optional since X-2021-11-23) [![](https://img.shields.io/badge/For-1.8%20--%201.17+-orange)](https://github.com/dmulloy2/ProtocolLib/releases/tag/4.7.0) [![](https://img.shields.io/badge/For-until%201.7-yellow)](https://github.com/dmulloy2/ProtocolLib/releases/tag/3.7.0) 10 | - Vault (optional) 11 | - economy plugin (optional) 12 | - PlaceholderAPI (optional) 13 | 14 | ### General 15 | 16 | A plugin for the Spigot API. ServerlistMOTD allows you to change your MOTD in the serverlist. You can set custom MOTDs for known players or welcome new players with a special MOTD to get the players attention. This plugin is HIGHLY compatibile with old and new versions of Bukkit/Spigot! 17 | 18 | Project page: https://dev.bukkit.org/projects/serverlistmotd 19 | 20 | ServerlistMOTD is one of the most popular serverlist plugins for the SpigotAPI with over 75,000 downloads. 21 | 22 | ![smotd](https://i.imgur.com/z3uzpYZ.png) 23 | 24 | ### Available Features 25 | 26 | You need ProtocolLib in order to gain access to all features. The table below lists the different feature sets. 27 | 28 | | Feature | Without ProtocolLib | With ProtocolLib | 29 | | ------------------ | ------------------- | ---------------- | 30 | | ClassicMotd | 🟢 | 🟢 | 31 | | RandomMotd | 🟢 | 🟢 | 32 | | BanMotd | 🟢 | 🟢 | 33 | | WhitelistMotd | 🟢 | 🟢 | 34 | | RestrictedMode | 🟠 | 🟢 | 35 | | FakeMaxPlayer | 🔴 | 🟢 | 36 | | FakeOnlinePlayer | 🔴 | 🟢 | 37 | | VersionText | 🔴 | 🟢 | 38 | | OutdatedClientText | 🔴 | 🟢 | 39 | | UnknownSlots | 🔴 | 🟢 | 40 | | SlotsPlusOne | 🔴 | 🟢 | 41 | | OnlineMultiplier | 🔴 | 🟢 | 42 | | HoverText | 🔴 | 🟢 | 43 | 44 | ### Support 45 | 46 | I started developing ServerlistMOTD in 2014 and slowly shifted away my focus from Spigot development. I did a small rewrite due to bad code in old versions and I dropped Bungeecord support. 47 | 48 | **This project is officially discontinued!** (I will probably look into it from time to time though.) 49 | 50 | ### License 51 | 52 | ServerlistMOTD is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 53 | http://creativecommons.org/licenses/by-nc-sa/3.0/ 54 | ! 55 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/events/ProtocolLibImplementation.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.events; 2 | 3 | import cloud.bolte.serverlistmotd.Main; 4 | import cloud.bolte.serverlistmotd.SpigotConfig; 5 | import cloud.bolte.serverlistmotd.slots.FakeOnlinePlayer; 6 | import cloud.bolte.serverlistmotd.slots.HoverText; 7 | import cloud.bolte.serverlistmotd.slots.OnlineMultiplier; 8 | import cloud.bolte.serverlistmotd.slots.OutdatedClientText; 9 | import cloud.bolte.serverlistmotd.slots.SlotsPlusOne; 10 | import cloud.bolte.serverlistmotd.slots.VersionText; 11 | import org.bukkit.Bukkit; 12 | 13 | import com.comphenix.protocol.PacketType; 14 | import com.comphenix.protocol.ProtocolLibrary; 15 | import com.comphenix.protocol.events.PacketAdapter; 16 | import com.comphenix.protocol.events.PacketEvent; 17 | import com.comphenix.protocol.wrappers.WrappedServerPing; 18 | 19 | /* 20 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 21 | * ServerlistMOTD is licensed under a 22 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 23 | * 24 | * You should have received a copy of the license along with this work. 25 | * If not, see . 26 | */ 27 | 28 | public class ProtocolLibImplementation { 29 | private static Main main; 30 | 31 | public ProtocolLibImplementation(Main plugin) { 32 | setPlugin(plugin); 33 | } 34 | 35 | private static void setPlugin(Main plugin) { 36 | main = plugin; 37 | } 38 | 39 | public void setupIntegration() { 40 | Bukkit.getLogger().info("[ServerlistMOTD] Hooking into ProtocolLib."); 41 | ProtocolLibrary.getProtocolManager().addPacketListener( 42 | new PacketAdapter(PacketAdapter.params(main, PacketType.Status.Server.SERVER_INFO).optionAsync()) { 43 | @Override 44 | public void onPacketSending(PacketEvent event) { 45 | WrappedServerPing ping = event.getPacket().getServerPings().read(0); 46 | 47 | if (SpigotConfig.fakeMaxPlayerEnabled()) { 48 | ping.setPlayersMaximum(SpigotConfig.getFakeMaxPlayerNumber()); 49 | } 50 | 51 | if (SpigotConfig.fakeOnlinePlayerEnabled()) { 52 | FakeOnlinePlayer.activateFakeOnlinePlayer(ping); 53 | } 54 | 55 | if (SpigotConfig.outdatedClientTextEnabled()) { 56 | OutdatedClientText.activate(ping); 57 | } 58 | 59 | if (SpigotConfig.versionTextEnabled()) { 60 | VersionText.activateVersionText(ping); 61 | } 62 | 63 | if (SpigotConfig.slotsPlusOneEnabled()) { 64 | SlotsPlusOne.acitvateSlotsPlusOne(ping); 65 | } 66 | 67 | if (SpigotConfig.onlineMultiplierEnabled()) { 68 | OnlineMultiplier.activateOnlineMultiplier(ping); 69 | } 70 | 71 | if (SpigotConfig.unknownSlotsEnabled()) { 72 | ping.setPlayersVisible(false); 73 | } 74 | 75 | // Unknown slots won't work if hover text is enabled as well. Result: 0/0 instead of ??? 76 | // I won't introduce a check here to not introduce unexpected behaviour with existing config.ymls 77 | if (SpigotConfig.hoverTextEnabled()) { // && !SpigotConfig.unknownSlotsEnabled() 78 | HoverText.activateHoverText(ping); 79 | } 80 | 81 | if (SpigotConfig.restrictedModeEnabled()) { 82 | ping.setVersionProtocol(-1); 83 | ping.setVersionName(SpigotConfig.getRestrictedVersionText()); // Rest happens in Ping.class 84 | } 85 | } 86 | }); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/Main.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd; 2 | 3 | import java.io.File; 4 | import java.net.InetAddress; 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | import java.util.UUID; 8 | 9 | import org.bukkit.Bukkit; 10 | import org.bukkit.event.Listener; 11 | import org.bukkit.plugin.java.JavaPlugin; 12 | import org.bukkit.scheduler.BukkitScheduler; 13 | 14 | import cloud.bolte.serverlistmotd.cmd.Serverlist; 15 | import cloud.bolte.serverlistmotd.events.IpLogging; 16 | import cloud.bolte.serverlistmotd.events.Ping; 17 | import cloud.bolte.serverlistmotd.events.ProtocolLibImplementation; 18 | import cloud.bolte.serverlistmotd.events.RestrictedModeJoin; 19 | import cloud.bolte.serverlistmotd.util.IO; 20 | import cloud.bolte.serverlistmotd.util.PapiIntegration; 21 | import cloud.bolte.serverlistmotd.util.VaultIntegration; 22 | 23 | /* 24 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 25 | * ServerlistMOTD is licensed under a 26 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 27 | * 28 | * You should have received a copy of the license along with this work. 29 | * If not, see . 30 | */ 31 | 32 | public class Main extends JavaPlugin implements Listener { 33 | public static Map IP_UUID = new HashMap<>(); 34 | private final File loggedIPs = new File("plugins/ServerlistMOTD/IP_UUID.dat"); 35 | 36 | @Override 37 | public void onDisable() { 38 | //Prepare HashMap and save it to disk 39 | IO.removeUnusedEntries(); 40 | IO.saveHashMapIntoFlatfile(loggedIPs, IP_UUID); 41 | } 42 | 43 | @Override 44 | public void onEnable() { 45 | //Write config if necessary and load Userdata in HashMap 46 | saveDefaultConfig(); 47 | IO.loadFlatfileIntoHashMap(loggedIPs, IP_UUID); 48 | 49 | SpigotConfig config = new SpigotConfig(this); 50 | 51 | //Setup Vault and Papi 52 | VaultIntegration.setupEconomy(); 53 | PapiIntegration.setupIntegration(); 54 | 55 | //Register listeners 56 | Bukkit.getServer().getPluginManager().registerEvents(new Ping(), this); 57 | Bukkit.getServer().getPluginManager().registerEvents(new IpLogging(), this); 58 | Bukkit.getServer().getPluginManager().registerEvents(new RestrictedModeJoin(), this); 59 | 60 | //Check if world set in config exists (time, weather var!) 61 | config.configWorldCheck(); 62 | 63 | //Try to hook into ProtocolLib for extended feature set 64 | if (Bukkit.getServer().getPluginManager().isPluginEnabled("ProtocolLib")) { 65 | ProtocolLibImplementation pli = new ProtocolLibImplementation(this); 66 | pli.setupIntegration(); 67 | } else { 68 | Bukkit.getLogger().warning("[ServerlistMOTD] ProtocolLib could not be loaded! You only have access to a reduced feature set."); 69 | Bukkit.getLogger().warning("[ServerlistMOTD] Disabled features: FakeMaxPlayer, FakeOnlinePlayer, VersionText, OutdatedClientText, UnknownSlots, SlotsPlusOne, OnlineMultiplier, HoverText"); 70 | } 71 | 72 | //Register command 73 | this.getCommand("serverlist").setExecutor(new Serverlist()); 74 | 75 | //Timer for saving userdata to disk 76 | BukkitScheduler scheduler = getServer().getScheduler(); 77 | scheduler.runTaskTimerAsynchronously(this, new Runnable() { 78 | @Override 79 | public void run() { 80 | IO.saveHashMapIntoFlatfile(loggedIPs, IP_UUID); 81 | } 82 | }, SpigotConfig.autoSaveIntervalInMin() * 1200L, SpigotConfig.autoSaveIntervalInMin() * 1200L); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/ban/SpigotBan.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.ban; 2 | 3 | import org.bukkit.Bukkit; 4 | import org.bukkit.BanList.Type; 5 | 6 | import cloud.bolte.serverlistmotd.SpigotConfig; 7 | 8 | /* 9 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 10 | * ServerlistMOTD is licensed under a 11 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 12 | * 13 | * You should have received a copy of the license along with this work. 14 | * If not, see . 15 | */ 16 | 17 | public class SpigotBan implements BanInterface { 18 | 19 | @Override 20 | public String banReason(String playerName) { 21 | return Bukkit.getBanList(Type.NAME).getBanEntry(playerName).getReason(); 22 | } 23 | 24 | @Override 25 | public Long expires(String playerName) { 26 | return Long.getLong(Bukkit.getBanList(Type.NAME).getBanEntry(playerName).getExpiration().toString()); 27 | } 28 | 29 | @Override 30 | public String banExpDateSec(String playerName) { 31 | return Bukkit.getBanList(Type.NAME).getBanEntry(playerName).getExpiration().getSeconds() + ""; 32 | } 33 | 34 | @Override 35 | public String banExpDateMin(String playerName) { 36 | return Bukkit.getBanList(Type.NAME).getBanEntry(playerName).getExpiration().getMinutes() + ""; 37 | } 38 | 39 | @Override 40 | public String banExpDateHour(String playerName) { 41 | return Bukkit.getBanList(Type.NAME).getBanEntry(playerName).getExpiration().getHours() + ""; 42 | } 43 | 44 | @Override 45 | public String banExpDateDay(String playerName) { 46 | return Bukkit.getBanList(Type.NAME).getBanEntry(playerName).getExpiration().getDay() + ""; 47 | } 48 | 49 | @Override 50 | public String banExpDateMonth(String playerName) { 51 | return Bukkit.getBanList(Type.NAME).getBanEntry(playerName).getExpiration().getMonth() + 1 + ""; 52 | } 53 | 54 | @Override 55 | public String banExpDateYear(String playerName) { 56 | return Bukkit.getBanList(Type.NAME).getBanEntry(playerName).getExpiration().getYear() - 100 + ""; 57 | 58 | } 59 | 60 | @Override 61 | public String date(String playerName) { 62 | return SpigotConfig.getFormatDate() 63 | .replace("DD", Bukkit.getBanList(Type.NAME).getBanEntry(playerName).getExpiration().getDate() + "") 64 | .replace("MM", Bukkit.getBanList(Type.NAME).getBanEntry(playerName).getExpiration().getMonth() + 1 + "") 65 | .replace("YYYY", Bukkit.getBanList(Type.NAME).getBanEntry(playerName).getExpiration().getYear() + 1900 + "") 66 | .replace("YY", Bukkit.getBanList(Type.NAME).getBanEntry(playerName).getExpiration().getYear() - 100 + ""); 67 | } 68 | 69 | @Override 70 | public String time(String playerName) { 71 | return SpigotConfig.getFormatTime() 72 | .replace("hh", Bukkit.getBanList(Type.NAME).getBanEntry(playerName).getExpiration().getHours() + "") 73 | .replace("mm", Bukkit.getBanList(Type.NAME).getBanEntry(playerName).getExpiration().getMinutes() + "") 74 | .replace("ss", Bukkit.getBanList(Type.NAME).getBanEntry(playerName).getExpiration().getSeconds() + ""); 75 | } 76 | 77 | @Override 78 | public String banActor(String playerName) { 79 | return Bukkit.getBanList(Type.NAME).getBanEntry(playerName).getTarget(); 80 | } 81 | 82 | @Override 83 | public String banCreated(String playerName) { 84 | return Bukkit.getBanList(Type.NAME).getBanEntry(playerName).getCreated() + ""; 85 | } 86 | 87 | @Override 88 | public String banID(String playerName) { 89 | return Bukkit.getBanList(Type.NAME).getBanEntry(playerName).getClass().toString(); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/motd/BanManagerMotd.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.motd; 2 | 3 | import java.net.InetAddress; 4 | import java.util.Date; 5 | 6 | import cloud.bolte.serverlistmotd.util.HexResolver; 7 | import org.bukkit.Bukkit; 8 | import org.bukkit.ChatColor; 9 | import org.bukkit.OfflinePlayer; 10 | import org.bukkit.event.server.ServerListPingEvent; 11 | 12 | import cloud.bolte.serverlistmotd.Main; 13 | import cloud.bolte.serverlistmotd.SpigotConfig; 14 | import cloud.bolte.serverlistmotd.ban.BanInterface; 15 | import cloud.bolte.serverlistmotd.ban.BanManager; 16 | import cloud.bolte.serverlistmotd.util.PapiIntegration; 17 | import cloud.bolte.serverlistmotd.variables.TimeVariable; 18 | import cloud.bolte.serverlistmotd.variables.WeatherVariable; 19 | import me.confuser.banmanager.common.api.BmAPI; 20 | //import me.confuser.banmanager.BmAPI; old version of BanManager 21 | 22 | /* 23 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 24 | * ServerlistMOTD is licensed under a 25 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 26 | * 27 | * You should have received a copy of the license along with this work. 28 | * If not, see . 29 | */ 30 | 31 | public class BanManagerMotd implements Motd{ 32 | 33 | @Override 34 | public String getMOTD(InetAddress ip) { 35 | if (BmAPI.getCurrentBan(Main.IP_UUID.get(ip)).getExpires() > 0.0) { 36 | return SpigotConfig.getBanTempMotd(); 37 | } else { 38 | return SpigotConfig.getBanForeverMotd(); 39 | } 40 | } 41 | 42 | // This needs to be cleaned up 43 | @Override 44 | public String formatMotd(String motd, InetAddress ip) { 45 | String formattedMotd; 46 | 47 | formattedMotd = ChatColor.translateAlternateColorCodes('&', motd); 48 | formattedMotd = formattedMotd.replace("%line%", "\n") 49 | .replace("%weather%", WeatherVariable.getWeather()) 50 | .replace("%time%", TimeVariable.getTime()); 51 | 52 | OfflinePlayer player = Bukkit.getOfflinePlayer(Main.IP_UUID.get(ip)); 53 | String playerName = player.getName(); 54 | 55 | if(playerName.equals(null)) { 56 | playerName = "Strumswell"; 57 | } 58 | 59 | BanInterface ban = new BanManager(); 60 | Date timestampconv = new Date((long) ban.expires(playerName) * 1000); 61 | 62 | // FULL BAN 63 | if (timestampconv.getYear() + 1900 == 1970) { 64 | formattedMotd = formattedMotd.replace("%reason%", ban.banReason(playerName)); 65 | // TEMP BAN 66 | } else { 67 | formattedMotd = formattedMotd.replace("%reason%", ban.banReason(playerName)) 68 | .replace("%expdate%", ban.date(playerName)) 69 | .replace("%exptime%", ban.time(playerName)) 70 | .replace("%expsec%", ban.banExpDateSec(playerName)) 71 | .replace("%expmin%", ban.banExpDateMin(playerName)) 72 | .replace("%exphour%", ban.banExpDateHour(playerName)) 73 | .replace("%expday%", ban.banExpDateDay(playerName)) 74 | .replace("%expmonth%", ban.banExpDateMonth(playerName)) 75 | .replace("%expyear%", ban.banExpDateYear(playerName)); 76 | } 77 | formattedMotd = PapiIntegration.replaceVariables(player, formattedMotd); 78 | formattedMotd = HexResolver.parseHexString(formattedMotd); 79 | return formattedMotd; 80 | } 81 | 82 | /** 83 | * Sets BanManager motd (external plugin) 84 | * according to if server knows player, formats and sets it. 85 | * 86 | * @param e ServerlistPingEvent from Spigot 87 | * @param ip IP of pinging player 88 | */ 89 | public void setServerlistMotd(ServerListPingEvent e, InetAddress ip) { 90 | if (Main.IP_UUID.containsKey(ip) && BmAPI.isBanned(Main.IP_UUID.get(ip))) { 91 | e.setMotd(formatMotd(getMOTD(ip), ip)); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/motd/BanMotd.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.motd; 2 | 3 | import java.net.InetAddress; 4 | 5 | import cloud.bolte.serverlistmotd.util.HexResolver; 6 | import org.bukkit.BanList.Type; 7 | import org.bukkit.Bukkit; 8 | import org.bukkit.ChatColor; 9 | import org.bukkit.OfflinePlayer; 10 | import org.bukkit.event.server.ServerListPingEvent; 11 | 12 | import cloud.bolte.serverlistmotd.Main; 13 | import cloud.bolte.serverlistmotd.SpigotConfig; 14 | import cloud.bolte.serverlistmotd.ban.BanInterface; 15 | import cloud.bolte.serverlistmotd.ban.SpigotBan; 16 | import cloud.bolte.serverlistmotd.util.PapiIntegration; 17 | import cloud.bolte.serverlistmotd.variables.RandomPlayerVariable; 18 | import cloud.bolte.serverlistmotd.variables.TimeVariable; 19 | import cloud.bolte.serverlistmotd.variables.WeatherVariable; 20 | 21 | /* 22 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 23 | * ServerlistMOTD is licensed under a 24 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 25 | * 26 | * You should have received a copy of the license along with this work. 27 | * If not, see . 28 | */ 29 | 30 | public class BanMotd implements Motd { 31 | 32 | @Override 33 | public String getMOTD(InetAddress ip) { 34 | //TEMP BAN 35 | if (Bukkit.getBanList(Type.NAME).getBanEntry(Bukkit.getOfflinePlayer(Main.IP_UUID.get(ip)).getName()) 36 | .getExpiration() != null) { 37 | return SpigotConfig.getBanTempMotd(); 38 | //FULL BAN 39 | } else 40 | return SpigotConfig.getBanForeverMotd(); 41 | } 42 | 43 | @Override 44 | public String formatMotd(String motd, InetAddress ip) { 45 | OfflinePlayer player = Bukkit.getOfflinePlayer(Main.IP_UUID.get(ip)); 46 | String playerName = player.getName(); 47 | String formattedMotd; 48 | 49 | formattedMotd = ChatColor.translateAlternateColorCodes('&', motd); 50 | formattedMotd = formattedMotd.replace("%line%", "\n") 51 | .replace("%weather%", WeatherVariable.getWeather()) 52 | .replace("%time%", TimeVariable.getTime()) 53 | .replace("%randomplayer%", RandomPlayerVariable.getRandomPlayer()); 54 | 55 | BanInterface ban = new SpigotBan(); 56 | 57 | // TEMP BAN 58 | if (Bukkit.getBanList(Type.NAME).getBanEntry(playerName).getExpiration() != null) { 59 | formattedMotd = formattedMotd.replace("%reason%", ban.banReason(playerName)) 60 | .replace("%expdate%", ban.date(playerName)) 61 | .replace("%exptime%", ban.time(playerName)) 62 | .replace("%expsec%", ban.banExpDateSec(playerName)) 63 | .replace("%expmin%", ban.banExpDateMin(playerName)) 64 | .replace("%exphour%", ban.banExpDateHour(playerName)) 65 | .replace("%expday%", ban.banExpDateDay(playerName)) 66 | .replace("%expmonth%", ban.banExpDateMonth(playerName)) 67 | .replace("%expyear%", ban.banExpDateYear(playerName)); 68 | // FULL BAN 69 | } else formattedMotd = formattedMotd.replace("%reason%", ban.banReason(playerName)); 70 | formattedMotd = PapiIntegration.replaceVariables(player, formattedMotd); 71 | formattedMotd = HexResolver.parseHexString(formattedMotd); 72 | return formattedMotd; 73 | } 74 | 75 | /** 76 | * Sets Ban motd (internal Spigot) 77 | * according to if server knows player, formats and sets it. 78 | * 79 | * @param e ServerlistPingEvent from Spigot 80 | * @param ip IP of pinging player 81 | */ 82 | public void setServerlistMotd(ServerListPingEvent e, InetAddress ip) { 83 | if (Main.IP_UUID.containsKey(ip)) { 84 | OfflinePlayer p = Bukkit.getOfflinePlayer(Main.IP_UUID.get(ip)); 85 | if (p.hasPlayedBefore() && p.isBanned()) { 86 | e.setMotd(formatMotd(getMOTD(ip), ip)); 87 | } 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/motd/MaxBansMotd.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.motd; 2 | 3 | import java.net.InetAddress; 4 | 5 | import cloud.bolte.serverlistmotd.util.HexResolver; 6 | import org.bukkit.Bukkit; 7 | import org.bukkit.ChatColor; 8 | import org.bukkit.OfflinePlayer; 9 | import org.bukkit.event.server.ServerListPingEvent; 10 | import org.maxgamer.maxbans.MaxBans; 11 | import org.maxgamer.maxbans.banmanager.TempBan; 12 | 13 | import cloud.bolte.serverlistmotd.Main; 14 | import cloud.bolte.serverlistmotd.SpigotConfig; 15 | import cloud.bolte.serverlistmotd.ban.BanInterface; 16 | import cloud.bolte.serverlistmotd.ban.MaxBansPlugin; 17 | import cloud.bolte.serverlistmotd.util.PapiIntegration; 18 | import cloud.bolte.serverlistmotd.variables.TimeVariable; 19 | import cloud.bolte.serverlistmotd.variables.WeatherVariable; 20 | 21 | /* 22 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 23 | * ServerlistMOTD is licensed under a 24 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 25 | * 26 | * You should have received a copy of the license along with this work. 27 | * If not, see . 28 | */ 29 | 30 | public class MaxBansMotd implements Motd { 31 | 32 | @Override 33 | public String getMOTD(InetAddress ip) { 34 | //Check for temp or full ban 35 | if (MaxBans.instance.getBanManager() 36 | .getBan(Bukkit.getOfflinePlayer(Main.IP_UUID.get(ip)).getName()) instanceof TempBan) { 37 | return SpigotConfig.getBanTempMotd(); 38 | } else { 39 | return SpigotConfig.getBanForeverMotd(); 40 | } 41 | } 42 | 43 | @Override 44 | public String formatMotd(String motd, InetAddress ip) { 45 | BanInterface ban = new MaxBansPlugin(); 46 | OfflinePlayer player = Bukkit.getOfflinePlayer(Main.IP_UUID.get(ip)); 47 | String playerName = player.getName(); 48 | String formattedMotd; 49 | 50 | formattedMotd = ChatColor.translateAlternateColorCodes('&', motd); 51 | formattedMotd = formattedMotd.replace("%line%", "\n") 52 | .replace("%weather%", WeatherVariable.getWeather()) 53 | .replace("%time%", TimeVariable.getTime()); 54 | 55 | // FULL BAN 56 | if (ban.expires(playerName) == 3555L) { 57 | formattedMotd = formattedMotd.replace("%reason%", ban.banReason(playerName)); 58 | // TEMP BAND 59 | } else { 60 | formattedMotd = formattedMotd 61 | .replace("%reason%", ban.banReason(playerName)) 62 | .replace("%expdate%", ban.date(playerName)).replace("%exptime%", ban.time(playerName)) 63 | .replace("%expsec%", ban.banExpDateSec(playerName)) 64 | .replace("%expmin%", ban.banExpDateMin(playerName)) 65 | .replace("%exphour%", ban.banExpDateHour(playerName)) 66 | .replace("%expday%", ban.banExpDateDay(playerName)) 67 | .replace("%expmonth%", ban.banExpDateMonth(playerName)) 68 | .replace("%expyear%", ban.banExpDateYear(playerName)); 69 | } 70 | formattedMotd = PapiIntegration.replaceVariables(player, formattedMotd); 71 | formattedMotd = HexResolver.parseHexString(formattedMotd); 72 | return formattedMotd; 73 | } 74 | 75 | /** 76 | * Sets MaxBans motd (external plugin) motd according to 77 | * if server knows player, formats and sets it. 78 | * 79 | * @param e ServerlistPingEvent from Spigot 80 | * @param ip IP of pinging player 81 | */ 82 | public void setServerlistMotd(ServerListPingEvent e, InetAddress ip) { 83 | if (Main.IP_UUID.containsKey(ip)) { 84 | //Check if player is known and set motd 85 | OfflinePlayer p = Bukkit.getOfflinePlayer(Main.IP_UUID.get(ip)); 86 | if (p.hasPlayedBefore()) { 87 | if (Main.IP_UUID.containsKey(ip) && MaxBans.instance.getBanManager().getBan(p.getName()) != null) { 88 | e.setMotd(formatMotd(getMOTD(ip), ip)); 89 | } 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/util/IO.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.util; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.File; 5 | import java.io.FileOutputStream; 6 | import java.io.FileReader; 7 | import java.io.IOException; 8 | import java.io.PrintWriter; 9 | import java.net.InetAddress; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | import java.util.Map.Entry; 13 | import java.util.UUID; 14 | 15 | import cloud.bolte.serverlistmotd.Main; 16 | import org.bukkit.Bukkit; 17 | 18 | /* 19 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 20 | * ServerlistMOTD is licensed under a 21 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 22 | * 23 | * You should have received a copy of the license along with this work. 24 | * If not, see . 25 | */ 26 | 27 | public class IO { 28 | 29 | private IO() { 30 | throw new IllegalStateException("Utility class"); 31 | } 32 | 33 | /** 34 | * Feed inmemory HashMap with known IPs and UUIDs to identify the player in the serverlist. 35 | * 36 | * @param f Flatfile 37 | * @param m HashMap containing IPs and UUIDs 38 | */ 39 | public static void loadFlatfileIntoHashMap(File f, Map m) { 40 | long start = System.currentTimeMillis(); 41 | if (f.exists()) { 42 | try { 43 | BufferedReader br = new BufferedReader(new FileReader(f)); 44 | String l; 45 | while ((l = br.readLine()) != null) { 46 | String[] t = l.split("=", 2); 47 | if (t.length != 2) 48 | continue; 49 | m.put(InetAddress.getByName(t[0].replaceAll("/", "")), UUID.fromString(t[1])); 50 | } 51 | br.close(); 52 | } catch (IOException ioe) { 53 | ioe.printStackTrace(); 54 | } 55 | Bukkit.getLogger().info("[ServerlistMOTD] Loaded userdata from IP_UUID.dat(" + f.length() + "bytes) into memory in " 56 | + (System.currentTimeMillis() - start) + "ms."); 57 | } 58 | } 59 | 60 | /** 61 | * Save inmemory HashMap into a Flatfile to store IPs and UUIDs longterm 62 | * 63 | * @param f Flatfile containing IPs and UUIDs 64 | * @param m Empty Hashmap 65 | */ 66 | public static void saveHashMapIntoFlatfile(File f, Map m) { 67 | try { 68 | FileOutputStream fos = new FileOutputStream(f); 69 | fos.flush(); 70 | fos.close(); 71 | PrintWriter pw = new PrintWriter(f); 72 | for (Map.Entry entry : m.entrySet()) 73 | pw.println(String.valueOf(entry.getKey()).replaceAll("/", "") + "=" + entry.getValue()); 74 | pw.flush(); 75 | pw.close(); 76 | } catch (IOException ioe) { 77 | ioe.printStackTrace(); 78 | } 79 | } 80 | 81 | /** 82 | * Invertes a HashMap 83 | * 84 | * @param map map to be inverted 85 | * @return Inverted HashMap 86 | */ 87 | private static Map invert(Map map) { 88 | Map result = new HashMap<>(); 89 | for (Entry entry : map.entrySet()) { 90 | result.put(entry.getValue(), entry.getKey()); 91 | } 92 | return result; 93 | } 94 | 95 | 96 | /** 97 | * Invertes HashMap two times to remove possible duplicates 98 | */ 99 | public static void removeUnusedEntries() { 100 | Main.IP_UUID = invert(invert(Main.IP_UUID)); 101 | } 102 | 103 | /** 104 | * Used for looking up a key in a HashMap. 105 | * Use try-catch-block to prevent NPE! 106 | * 107 | * @param hm HashMap 108 | * @param value Value in HashMap 109 | * @return key of requested value in HashMap 110 | */ 111 | public static Object getKeyFromValue(Map hm, Object value) { 112 | for (Object o : hm.keySet()) { 113 | if (hm.get(o).equals(value)) { 114 | return o; 115 | } 116 | } 117 | return null; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/ban/MaxBansPlugin.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.ban; 2 | 3 | import java.util.Date; 4 | 5 | import org.maxgamer.maxbans.MaxBans; 6 | import org.maxgamer.maxbans.banmanager.Ban; 7 | import org.maxgamer.maxbans.banmanager.TempBan; 8 | 9 | import cloud.bolte.serverlistmotd.SpigotConfig; 10 | 11 | /* 12 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 13 | * ServerlistMOTD is licensed under a 14 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 15 | * 16 | * You should have received a copy of the license along with this work. 17 | * If not, see . 18 | */ 19 | 20 | public class MaxBansPlugin implements BanInterface { 21 | 22 | public Ban getBan(String playerName) { 23 | return MaxBans.instance.getBanManager().getBan(playerName); 24 | } 25 | 26 | @Override 27 | public String banReason(String playerName) { 28 | return getBan(playerName).getReason(); 29 | } 30 | 31 | @Override 32 | public Long expires(String playerName) { 33 | if (getBan(playerName) instanceof TempBan) { 34 | TempBan temp = (TempBan) getBan(playerName); 35 | return temp.getExpires(); 36 | } else { 37 | return 3555L; 38 | } 39 | } 40 | 41 | @Override 42 | public String banExpDateSec(String playerName) { 43 | if (this.expires(playerName) != null) { 44 | Date timestampconv = new Date(this.expires(playerName)); 45 | return timestampconv.getSeconds() + ""; 46 | } else { 47 | return "0"; 48 | } 49 | } 50 | 51 | @Override 52 | public String banExpDateMin(String playerName) { 53 | if (this.expires(playerName) != null) { 54 | Date timestampconv = new Date(this.expires(playerName)); 55 | return timestampconv.getMinutes() + ""; 56 | } else { 57 | return "0"; 58 | } 59 | } 60 | 61 | @Override 62 | public String banExpDateHour(String playerName) { 63 | if (this.expires(playerName) != null) { 64 | Date timestampconv = new Date(this.expires(playerName)); 65 | return timestampconv.getHours() + ""; 66 | } else { 67 | return "0"; 68 | } 69 | } 70 | 71 | @Override 72 | public String banExpDateDay(String playerName) { 73 | if (this.expires(playerName) != null) { 74 | Date timestampconv = new Date(this.expires(playerName)); 75 | return timestampconv.getDate() + ""; 76 | } else { 77 | return "0"; 78 | } 79 | } 80 | 81 | @Override 82 | public String banExpDateMonth(String playerName) { 83 | if (this.expires(playerName) != null) { 84 | Date timestampconv = new Date(this.expires(playerName)); 85 | return timestampconv.getMonth() + 1 + ""; 86 | } else { 87 | return "0"; 88 | } 89 | } 90 | 91 | @Override 92 | public String banExpDateYear(String playerName) { 93 | if (this.expires(playerName) != null) { 94 | Date timestampconv = new Date(this.expires(playerName)); 95 | return timestampconv.getYear() - 100 + ""; 96 | } else { 97 | return "0"; 98 | } 99 | } 100 | 101 | @Override 102 | public String date(String playerName) { 103 | if (this.expires(playerName) != null) { 104 | Date timestampconv = new Date(this.expires(playerName)); 105 | return SpigotConfig.getFormatDate().replace("DD", banExpDateDay(playerName)) 106 | .replace("MM", banExpDateMonth(playerName)) 107 | .replace("YYYY", timestampconv.getYear() + 1900 + "") 108 | .replace("YY", banExpDateYear(playerName)); 109 | } else { 110 | return "0"; 111 | } 112 | } 113 | 114 | @Override 115 | public String time(String playerName) { 116 | if (this.expires(playerName) != null) { 117 | return SpigotConfig.getFormatTime().replace("hh", banExpDateHour(playerName)) 118 | .replace("mm", banExpDateMin(playerName)).replace("ss", banExpDateSec(playerName)); 119 | } else { 120 | return "0"; 121 | } 122 | } 123 | 124 | @Override 125 | public String banActor(String playerName) { 126 | return playerName; 127 | } 128 | 129 | @Override 130 | public String banCreated(String playerName) { 131 | return getBan(playerName).getCreated() + ""; 132 | } 133 | 134 | @Override 135 | public String banID(String playerName) { 136 | return getBan(playerName).getId(); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/cmd/Serverlist.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.cmd; 2 | 3 | import org.bukkit.command.Command; 4 | import org.bukkit.command.CommandExecutor; 5 | import org.bukkit.command.CommandSender; 6 | 7 | import cloud.bolte.serverlistmotd.SpigotConfig; 8 | 9 | /* 10 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 11 | * ServerlistMOTD is licensed under a 12 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 13 | * 14 | * You should have received a copy of the license along with this work. 15 | * If not, see . 16 | */ 17 | 18 | public class Serverlist implements CommandExecutor { 19 | 20 | @Override 21 | public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) { 22 | if (cmd.getName().equalsIgnoreCase("serverlist")) { 23 | switch(args.length) { 24 | case 0: 25 | sender.sendMessage("§8§l---------------------------------"); 26 | sender.sendMessage("§e§lServerlist§6§lMOTD"); 27 | sender.sendMessage("§7 §o~by Strumswell"); 28 | sender.sendMessage("§8§l---------------------------------"); 29 | sender.sendMessage("§6§l> §eList of commands:"); 30 | sender.sendMessage(" §e/serverlist §7§o* help screen"); 31 | sender.sendMessage(" §e/serverlist reload §7§o* reload config"); 32 | sender.sendMessage(" §e/serverlist restrictedmode §7§o* toggle function"); 33 | sender.sendMessage(" §e/serverlist versiontext §7§o* toggle function"); 34 | sender.sendMessage(" §e/serverlist randommotd §7§o* toggle function"); 35 | sender.sendMessage(" §e/serverlist banmotd §7§o* toggle function"); 36 | sender.sendMessage(" §e/serverlist whitelistmotd §7§o* toggle function"); 37 | sender.sendMessage(" §e/serverlist hovertext §7§o* toggle function"); 38 | sender.sendMessage(" §e/serverlist unknownslots §7§o* toggle function"); 39 | return true; 40 | case 1: 41 | if (args[0].equalsIgnoreCase("reload")) { 42 | if (sender.hasPermission("serverlist.reload")) { 43 | SpigotConfig.reloadSmotdConfig(sender); 44 | } else sender.sendMessage("§e§oServerlist§6§lMOTD §7> §cYou don't have permissions!"); 45 | return true; 46 | } else if (args[0].equalsIgnoreCase("restrictedmode")) { 47 | if (sender.hasPermission("serverlist.restrictedmode")) { 48 | SpigotConfig.toggleRestrictedMode(sender); 49 | } else sender.sendMessage("§e§oServerlist§6§lMOTD §7> §cYou don't have permissions!"); 50 | return true; 51 | } else if (args[0].equalsIgnoreCase("versiontext")) { 52 | if (sender.hasPermission("serverlist.versiontext")) { 53 | SpigotConfig.toggleVersionText(sender); 54 | } else sender.sendMessage("§e§oServerlist§6§lMOTD §7> §cYou don't have permissions!"); 55 | return true; 56 | } else if (args[0].equalsIgnoreCase("randommotd")) { 57 | if (sender.hasPermission("serverlist.randommotd")) { 58 | SpigotConfig.toggleRandomMotd(sender); 59 | } else sender.sendMessage("§e§oServerlist§6§lMOTD §7> §cYou don't have permissions!"); 60 | return true; 61 | } else if (args[0].equalsIgnoreCase("banmotd")) { 62 | if (sender.hasPermission("serverlist.banmotd")) { 63 | SpigotConfig.toggleBanMotd(sender); 64 | } else sender.sendMessage("§e§oServerlist§6§lMOTD §7> §cYou don't have permissions!"); 65 | return true; 66 | } else if (args[0].equalsIgnoreCase("whitelistmotd")) { 67 | if (sender.hasPermission("serverlist.whitelistmotd")) { 68 | SpigotConfig.toggleWhitelistMotd(sender); 69 | } else sender.sendMessage("§e§oServerlist§6§lMOTD §7> §cYou don't have permissions!"); 70 | return true; 71 | } else if (args[0].equalsIgnoreCase("hovertext")) { 72 | if (sender.hasPermission("serverlist.hovertext")) { 73 | SpigotConfig.toggleHoverText(sender); 74 | } else sender.sendMessage("§e§oServerlist§6§lMOTD §7> §cYou don't have permissions!"); 75 | return true; 76 | } else if (args[0].equalsIgnoreCase("unknownslots")) { 77 | if (sender.hasPermission("serverlist.unknownslots")) { 78 | SpigotConfig.toggleUnknownSlots(sender); 79 | } else sender.sendMessage("§e§oServerlist§6§lMOTD §7> §cYou don't have permissions!"); 80 | return true; 81 | } else return false; 82 | default: 83 | // 84 | } 85 | } 86 | return false; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /config.yml: -------------------------------------------------------------------------------- 1 | # ----------------------------------------- [ Configuration File ] ------------------------------------------ # 2 | # FAQ: 3 | # - "Why IP Logging?": Needed for identifying players in the serverlist by their IP. Used in %player%, %money" 4 | # IPs and UUIDs of players are stored locally inside the IP_UUID.dat. 5 | # - "Connection turns red in serverlist with VersionText on.": Ever seen when your server is outdated in the 6 | # serverlist? SMOTD simulates this and changes the text. This is just cosmetical! 7 | # - "Plugin ServerlistMOTD created a profile with 'HoverText' as an UUID.": Your HoverText normally 8 | # contains a list of players. SMOTD clears that and creates a fake player with your text as its name. 9 | # - "What is Regulars and Newbies?" Players are categorized in those two groups in the list. Regular players 10 | # are known by their ip while newbies are not. 11 | # - "Player related placeholders from PlaceholderAPI are not working!": This is a known limitation. All this 12 | # information is not available in the serverlist because the player isn't online. 13 | # ----------------------------------------- [ Configuration File ] ------------------------------------------ # 14 | 15 | ClassicMotd: 16 | Regulars: '&2Welcome back, &e%player%&2! %line%&aIt''s a %weather% %time%.' 17 | Newbies: '&2Welcome newbie! %line%&aIt''s a %weather% %time%.' 18 | RandomMotd: 19 | Enable: false 20 | Regulars: 21 | - '&bHey %player%! %line%&3Those Motds change totally random!' 22 | - '&2You can add as many Motds as you want!' 23 | - '&eAdd bullet points to add more Motds!' 24 | - '&3The weather is %weather% and it is %time%' 25 | Newbies: 26 | - '&bHey Newbie. %line%&3Those Motds change totally random!' 27 | - '&2You can add as many Motds as you want!' 28 | - '&eAdd bullet points to add more Motds!' 29 | - '&3The weather is %weather% and it is %time%.' 30 | BanMotd: 31 | Enable: false 32 | MessageTempBan: '&cYou are banned! Reason: &e%reason%%line%&cExpiration: &e%expdate% at %exptime%' 33 | MessageForeverBan: '&cYou are banned! Reason: &e%reason%%line%&cExpiration: &eNEVER' 34 | Format: 35 | Date: 'DD/MM/YYYY' 36 | Time: 'hh:mm:ss' 37 | WhitelistMotd: 38 | Enable: false 39 | MessageWhitelisted: '&cWelcome back, &e%player%&c!%line%&c&oYou are on the whitelist.' 40 | MessageNotWhitelisted: '&cYou are &lNOT &cwhitelisted.%line%&c&oPlease contact the server owner.' 41 | RestrictedMode: 42 | Enable: false 43 | Motd: 44 | AccessGranted: '&4Server is in restricted mode! You are able to join.' 45 | AccessDenied: '&4Can''t connect to server.' 46 | KickMessage: 'java.net.ConnectException: Connection timed out: no further information:' 47 | Slots: 48 | VersionText: '' 49 | Slots: 50 | FakeMaxPlayer: 51 | Enable: false 52 | Number: 200 53 | FakeOnlinePlayer: 54 | Enable: false 55 | Number: 122 56 | RandomNumber: 57 | Enable: false 58 | Max: 100 59 | Min: 90 60 | VersionText: 61 | Enable: false 62 | Message: '&aJoin now! &e%realonline%/%realslots%' 63 | OutdatedClientText: 64 | Enable: false 65 | Message: 'Use Minecraft 1.16 &r&7%realonline%&8/&7%realslots%' 66 | UnknownSlots: 67 | Enable: false 68 | SlotsPlusOne: 69 | Enable: false 70 | MinSlots: 5 71 | MaxSlots: 100 72 | AddSlotsToOnline: 1 73 | OnlineMultiplier: 74 | Enable: false 75 | MinSlots: 100 76 | MaxSlots: 2500 77 | AddSlotsWhenOnline>MinSlots: 1 78 | MultiplyBy: 5 79 | HoverText: 80 | Enable: false 81 | Messages: 82 | - '&7>>>>>>> &6ServerlistMOTD &7<<<<<<<' 83 | - ' &e-> This is a TEST!' 84 | - ' &e-> Strumswell loves you. &c&l<3' 85 | - '&eAdd lines by adding bullet points!' 86 | Variables: 87 | TimeVariable: 88 | NightText: night 89 | DayText: day 90 | World: world 91 | WeatherVariable: 92 | RainText: rainy 93 | SunText: clear 94 | World: world 95 | RandomNumberVariable: 96 | Max: 100 97 | Min: 90 98 | RandomPlayerVariable: 99 | UseTextWhenNobodyOnline: 100 | Enable: false 101 | Text: 'Player' 102 | UseDatabaseNameWhenNobodyOnline: 103 | Enable: true 104 | AutoSaveConfig: 105 | IntervalInMin: 30 106 | DoNOTtouchMe: 10.1 -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/ban/BanManager.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.ban; 2 | 3 | import java.util.UUID; 4 | 5 | import org.bukkit.Bukkit; 6 | 7 | import cloud.bolte.serverlistmotd.SpigotConfig; 8 | import me.confuser.banmanager.common.api.BmAPI; 9 | //import me.confuser.banmanager.BmAPI; old version of BanManager 10 | 11 | /* 12 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 13 | * ServerlistMOTD is licensed under a 14 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 15 | * 16 | * You should have received a copy of the license along with this work. 17 | * If not, see . 18 | */ 19 | 20 | public class BanManager implements BanInterface { 21 | 22 | public UUID getUUID(String playerName) { 23 | return Bukkit.getOfflinePlayer(playerName).getUniqueId(); 24 | } 25 | 26 | @Override 27 | public String banReason(String playerName) { 28 | return BmAPI.getCurrentBan(playerName).getReason(); 29 | } 30 | 31 | @Override 32 | public String banExpDateSec(String playerName) { 33 | if (this.expires(playerName) != null) { 34 | java.util.Date timestampconv = new java.util.Date((long) this.expires(playerName) * 1000); 35 | return timestampconv.getSeconds() + ""; 36 | } else { 37 | return "0"; 38 | } 39 | } 40 | 41 | @Override 42 | public Long expires(String playerName) { 43 | return BmAPI.getCurrentBan(playerName).getExpires(); 44 | } 45 | 46 | @Override 47 | public String banExpDateMin(String playerName) { 48 | if (this.expires(playerName) != null) { 49 | java.util.Date timestampconv = new java.util.Date((long) this.expires(playerName) * 1000); 50 | return timestampconv.getMinutes() + ""; 51 | } else { 52 | return "0"; 53 | } 54 | } 55 | 56 | @Override 57 | public String banExpDateHour(String playerName) { 58 | if (this.expires(playerName) != null) { 59 | java.util.Date timestampconv = new java.util.Date((long) this.expires(playerName) * 1000); 60 | return timestampconv.getHours() + ""; 61 | } else { 62 | return "0"; 63 | } 64 | } 65 | 66 | @Override 67 | public String banExpDateDay(String playerName) { 68 | if (this.expires(playerName) != null) { 69 | java.util.Date timestampconv = new java.util.Date((long) this.expires(playerName) * 1000); 70 | return timestampconv.getDate() + ""; 71 | } else { 72 | return "0"; 73 | } 74 | } 75 | 76 | @Override 77 | public String banExpDateMonth(String playerName) { 78 | if (this.expires(playerName) != null) { 79 | java.util.Date timestampconv = new java.util.Date((long) this.expires(playerName) * 1000); 80 | return timestampconv.getMonth() + 1 + ""; 81 | } else { 82 | return "0"; 83 | } 84 | } 85 | 86 | @Override 87 | public String banExpDateYear(String playerName) { 88 | if (this.expires(playerName) != null) { 89 | java.util.Date timestampconv = new java.util.Date((long) this.expires(playerName) * 1000); 90 | return timestampconv.getYear() - 100 + ""; 91 | } else { 92 | return "0"; 93 | } 94 | } 95 | 96 | @Override 97 | public String date(String playerName) { 98 | if (this.expires(playerName) != null) { 99 | java.util.Date timestampconv = new java.util.Date((long) this.expires(playerName) * 1000); 100 | return SpigotConfig.getFormatDate().replaceAll("DD", banExpDateDay(playerName)) 101 | .replaceAll("MM", banExpDateMonth(playerName)) 102 | .replaceAll("YYYY", timestampconv.getYear() + 1900 + "") 103 | .replaceAll("YY", banExpDateYear(playerName)); 104 | } else { 105 | return "0"; 106 | } 107 | } 108 | 109 | @Override 110 | public String time(String playerName) { 111 | if (this.expires(playerName) != null) { 112 | return SpigotConfig.getFormatTime().replaceAll("hh", banExpDateHour(playerName)) 113 | .replaceAll("mm", banExpDateMin(playerName)).replaceAll("ss", banExpDateSec(playerName)); 114 | } else { 115 | return "0"; 116 | } 117 | } 118 | 119 | @Override 120 | public String banActor(String playerName) { 121 | return BmAPI.getCurrentBan(playerName).getActor().getName(); 122 | } 123 | 124 | @Override 125 | public String banCreated(String playerName) { 126 | return String.valueOf(BmAPI.getCurrentBan(playerName).getCreated()); 127 | } 128 | 129 | @Override 130 | public String banID(String playerName) { 131 | return String.valueOf(BmAPI.getCurrentBan(playerName).getId()); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/util/HexResolver.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd.util; 2 | 3 | import net.md_5.bungee.api.ChatColor; 4 | import java.util.regex.Matcher; 5 | import java.util.Arrays; 6 | import java.util.regex.Pattern; 7 | import java.util.stream.Collectors; 8 | import java.awt.Color; 9 | import java.util.List; 10 | 11 | /** 12 | * Credits go to harry0198 https://github.com/harry0198/HexiTextLib MIT License 13 | * Small edits done by Strumswell 14 | */ 15 | public class HexResolver { 16 | private static final Pattern GRADIENT_PATTERN = Pattern.compile("<(gradient|g)(:#([a-fA-F0-9]){6})+>"); 17 | private static final Pattern HEX_PATTERN = Pattern.compile("<(#[a-fA-F0-9]{6})>"); 18 | private static final Pattern STOPPING_PATTERN = Pattern.compile("<(gradient|g)(:#([a-fA-F0-9]){6})+>|(§[a-fA-F0-9])|<(#[a-fA-F0-9]{6})>"); 19 | 20 | /** 21 | * Checks if hex colour codes are supported for the version of minecraft. 22 | * @return True if supports hex. False if not. 23 | */ 24 | public static boolean serverSupportsHex() { 25 | try { 26 | ChatColor.of(Color.BLACK); 27 | return true; 28 | } catch (NoSuchMethodError ignore) { 29 | return false; 30 | } 31 | } 32 | 33 | /** 34 | * Parses string into hex colours where applicable using custom pattern matcher 35 | * @param text String to parse into hex 36 | * @return Parsed Hex where applicable otherwise returns inputted string 37 | */ 38 | public static String parseHexString(String text, Pattern hexPattern) { 39 | if (serverSupportsHex()) { 40 | text = parseGradients(text); 41 | Matcher hexColorMatcher = hexPattern.matcher(text); 42 | while (hexColorMatcher.find()) { 43 | String hex = hexColorMatcher.group(1); 44 | ChatColor color = ChatColor.of(hex); 45 | 46 | String before = text.substring(0, hexColorMatcher.start()); 47 | String after = text.substring(hexColorMatcher.end()); 48 | text = before + color + after; 49 | hexColorMatcher = hexPattern.matcher(text); 50 | 51 | } 52 | } 53 | return org.bukkit.ChatColor.translateAlternateColorCodes('&',text); 54 | } 55 | 56 | /** 57 | * Parses string into hex colours where applicable using default pattern matcher 58 | * @param text String to parse into hex 59 | * @return Parsed Hex where applicable otherwise returns inputted string 60 | */ 61 | public static String parseHexString(String text) { 62 | return parseHexString(text, HexResolver.HEX_PATTERN); 63 | } 64 | 65 | /** 66 | * Parses string into a gradient colour coded string 67 | * @param text String to parse 68 | * @return String with gradient applied 69 | */ 70 | private static String parseGradients(String text) { 71 | List formatCodes = Arrays.asList("§o", "§k", "§l", "§n", "§r", "§m"); 72 | String parsed = text; 73 | 74 | Matcher matcher = GRADIENT_PATTERN.matcher(parsed); 75 | while (matcher.find()) { 76 | StringBuilder parsedGradient = new StringBuilder(); 77 | 78 | String match = matcher.group(); 79 | int tagLength = match.startsWith(""); 82 | String hexContent = match.substring(tagLength, indexOfClose); 83 | List hexSteps = Arrays.stream(hexContent.split(":")).map(Color::decode).collect(Collectors.toList()); 84 | 85 | int stop = findGradientStop(parsed, matcher.end()); 86 | String content = parsed.substring(matcher.end(), stop); 87 | 88 | String cleanedContent = content; 89 | for (String code: formatCodes) { 90 | cleanedContent = cleanedContent.replace(code, ""); 91 | } 92 | 93 | Gradient gradient = new Gradient(hexSteps, cleanedContent.length()); 94 | 95 | String tempFormat = ""; 96 | for (char c : content.toCharArray()) { 97 | if (c != '§' && tempFormat != "§") { 98 | // This is a normal char 99 | parsedGradient 100 | .append(ChatColor.of(gradient.next()).toString()) 101 | .append(tempFormat) 102 | .append(c); 103 | } else if (c == '§') { 104 | // A custom formatting is starting 105 | tempFormat = "§"; 106 | } else if (c != '§' && tempFormat.contains("§")) { 107 | // Type of custom formatting defined now 108 | tempFormat += c; 109 | } 110 | } 111 | 112 | String before = parsed.substring(0, matcher.start()); 113 | String after = parsed.substring(stop); 114 | parsed = before + parsedGradient + after; 115 | matcher = GRADIENT_PATTERN.matcher(parsed); 116 | } 117 | return parsed; 118 | } 119 | 120 | /** 121 | * Returns the index of the colour that is about to change to the next 122 | * 123 | * @param content The content to search through 124 | * @param searchAfter The index at which to search after 125 | * @return the index of the color stop, or the end of the string index if none is found 126 | */ 127 | private static int findGradientStop(String content, int searchAfter) { 128 | Matcher matcher = STOPPING_PATTERN.matcher(content); 129 | while (matcher.find()) { 130 | if (matcher.start() > searchAfter) 131 | return matcher.start(); 132 | } 133 | return content.length() - 1; 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/cloud/bolte/serverlistmotd/SpigotConfig.java: -------------------------------------------------------------------------------- 1 | package cloud.bolte.serverlistmotd; 2 | 3 | import java.io.File; 4 | import java.util.List; 5 | 6 | import org.bukkit.Bukkit; 7 | import org.bukkit.World; 8 | import org.bukkit.command.CommandSender; 9 | import org.bukkit.entity.Player; 10 | 11 | import cloud.bolte.serverlistmotd.motd.MotdState; 12 | 13 | /* 14 | * ServerlistMOTD (c) by Strumswell, Philipp Bolte 15 | * ServerlistMOTD is licensed under a 16 | * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 17 | * 18 | * You should have received a copy of the license along with this work. 19 | * If not, see . 20 | */ 21 | 22 | // TODO: Migration for OutdatedClientText from older version 23 | public class SpigotConfig { 24 | private static Main main; 25 | 26 | public SpigotConfig(Main plugin) { 27 | setPlugin(plugin); 28 | migrateConfig(); 29 | } 30 | 31 | private static void setPlugin(Main plugin) { 32 | main = plugin; 33 | } 34 | /* 35 | * ClassicMotd 36 | */ 37 | public static String getNewbieMotd() { 38 | return main.getConfig().getString("ClassicMotd.Newbies"); 39 | } 40 | 41 | public static String getRegularsMotd() { 42 | return main.getConfig().getString("ClassicMotd.Regulars"); 43 | } 44 | 45 | /* 46 | * RandomMotd 47 | */ 48 | public static List getNewbieRandomMotd() { 49 | return main.getConfig().getStringList("RandomMotd.Newbies"); 50 | } 51 | 52 | public static List getRegularsRandomMotd() { 53 | return main.getConfig().getStringList("RandomMotd.Regulars"); 54 | } 55 | 56 | public static boolean randomMotdEnabled() { 57 | return main.getConfig().getBoolean("RandomMotd.Enable"); 58 | } 59 | 60 | /* 61 | * BanMotd 62 | */ 63 | public static String getBanTempMotd() { 64 | return main.getConfig().getString("BanMotd.MessageTempBan"); 65 | } 66 | 67 | public static String getBanForeverMotd() { 68 | return main.getConfig().getString("BanMotd.MessageForeverBan"); 69 | } 70 | 71 | public static boolean banMotdEnabled() { 72 | return main.getConfig().getBoolean("BanMotd.Enable"); 73 | } 74 | 75 | public static String getFormatDate() { 76 | return main.getConfig().getString("BanMotd.Format.Date"); 77 | } 78 | 79 | public static String getFormatTime() { 80 | return main.getConfig().getString("BanMotd.Format.Time"); 81 | } 82 | 83 | /* 84 | * WhitelistMotd 85 | */ 86 | public static String getWhitelistMotd() { 87 | return main.getConfig().getString("WhitelistMotd.MessageWhitelisted"); 88 | } 89 | 90 | public static String getNotWhitelistedMotd() { 91 | return main.getConfig().getString("WhitelistMotd.MessageNotWhitelisted"); 92 | } 93 | 94 | public static boolean whitelistMotdEnabled() { 95 | return main.getConfig().getBoolean("WhitelistMotd.Enable"); 96 | } 97 | 98 | /* 99 | * RestrictedMode 100 | */ 101 | public static String getRestrictedAccessGrantedMotd() { 102 | return main.getConfig().getString("RestrictedMode.Motd.AccessGranted"); 103 | } 104 | 105 | public static String getRestrictedAccessDeniedMotd() { 106 | return main.getConfig().getString("RestrictedMode.Motd.AccessDenied"); 107 | } 108 | 109 | public static String getRestrictedKickMessage() { 110 | return main.getConfig().getString("RestrictedMode.Motd.KickMessage"); 111 | } 112 | 113 | public static String getRestrictedVersionText() { 114 | return main.getConfig().getString("RestrictedMode.Slots.VersionText"); 115 | } 116 | 117 | public static boolean restrictedModeEnabled() { 118 | return main.getConfig().getBoolean("RestrictedMode.Enable"); 119 | } 120 | 121 | /* 122 | * FakeMaxPlayer 123 | */ 124 | public static boolean fakeMaxPlayerEnabled() { 125 | return main.getConfig().getBoolean("Slots.FakeMaxPlayer.Enable"); 126 | } 127 | 128 | public static int getFakeMaxPlayerNumber() { 129 | return main.getConfig().getInt("Slots.FakeMaxPlayer.Number"); 130 | } 131 | 132 | /* 133 | * FakeOnlinePlayer 134 | */ 135 | public static boolean fakeOnlinePlayerEnabled() { 136 | return main.getConfig().getBoolean("Slots.FakeOnlinePlayer.Enable"); 137 | } 138 | 139 | public static boolean fakeOnlinePlayerRandomNumberEnabled() { 140 | return main.getConfig().getBoolean("Slots.FakeOnlinePlayer.RandomNumber.Enable"); 141 | } 142 | 143 | public static int getfakeOnlinePlayerRandomNumberMax() { 144 | return main.getConfig().getInt("Slots.FakeOnlinePlayer.RandomNumber.Max"); 145 | } 146 | 147 | public static int getfakeOnlinePlayerRandomNumberMin() { 148 | return main.getConfig().getInt("Slots.FakeOnlinePlayer.RandomNumber.Min"); 149 | } 150 | 151 | public static int getFakeOnlinePlayerNumber() { 152 | return main.getConfig().getInt("Slots.FakeOnlinePlayer.Number"); 153 | } 154 | 155 | /* 156 | * VersionText 157 | */ 158 | public static String getVersionText() { 159 | return main.getConfig().getString("Slots.VersionText.Message"); 160 | } 161 | 162 | public static boolean versionTextEnabled() { 163 | return main.getConfig().getBoolean("Slots.VersionText.Enable"); 164 | } 165 | 166 | /* 167 | * OutdatedClientText 168 | */ 169 | public static String getOudatedClientText() { 170 | return main.getConfig().getString("Slots.OutdatedClientText.Message"); 171 | } 172 | 173 | public static boolean outdatedClientTextEnabled() { 174 | return main.getConfig().getBoolean("Slots.OutdatedClientText.Enable"); 175 | } 176 | 177 | /* 178 | * UnkownSlots 179 | */ 180 | public static boolean unknownSlotsEnabled() { 181 | return main.getConfig().getBoolean("Slots.UnknownSlots.Enable"); 182 | } 183 | 184 | /* 185 | * SlotsPlusOne 186 | */ 187 | public static boolean slotsPlusOneEnabled() { 188 | return main.getConfig().getBoolean("Slots.SlotsPlusOne.Enable"); 189 | } 190 | 191 | public static int getSlotsPlusOneMinSlots() { 192 | return main.getConfig().getInt("Slots.SlotsPlusOne.MinSlots"); 193 | } 194 | 195 | public static int getSlotsPlusOneMaxSlots() { 196 | return main.getConfig().getInt("Slots.SlotsPlusOne.MaxSlots"); 197 | } 198 | 199 | public static int getSlotsPlusOneAddSlotsToOnline() { 200 | return main.getConfig().getInt("Slots.SlotsPlusOne.AddSlotsToOnline"); 201 | } 202 | 203 | /* 204 | * OnlineMultiplier 205 | */ 206 | public static boolean onlineMultiplierEnabled() { 207 | return main.getConfig().getBoolean("Slots.OnlineMultiplier.Enable"); 208 | } 209 | 210 | public static int getOnlineMultiplierMinSlots() { 211 | return main.getConfig().getInt("Slots.OnlineMultiplier.MinSlots"); 212 | } 213 | 214 | public static int getOnlineMultiplierMaxSlots() { 215 | return main.getConfig().getInt("Slots.OnlineMultiplier.MaxSlots"); 216 | } 217 | 218 | public static int getOnlineMultiplierAddSlots() { 219 | return main.getConfig().getInt("Slots.OnlineMultiplier.AddSlotsWhenOnline>MinSlots"); 220 | } 221 | 222 | public static double getOnlineMultiplier() { 223 | return main.getConfig().getDouble("Slots.OnlineMultiplier.MultiplyBy"); 224 | } 225 | 226 | /* 227 | * HoverText 228 | */ 229 | public static List getHoverText() { 230 | return main.getConfig().getStringList("Slots.HoverText.Messages"); 231 | } 232 | 233 | public static boolean hoverTextEnabled() { 234 | return main.getConfig().getBoolean("Slots.HoverText.Enable"); 235 | } 236 | 237 | /* 238 | * TimeVar 239 | */ 240 | public static String getTimeWorld() { 241 | return main.getConfig().getString("Variables.TimeVariable.World"); 242 | } 243 | 244 | public static String getDayText() { 245 | return main.getConfig().getString("Variables.TimeVariable.DayText"); 246 | } 247 | 248 | public static String getNightText() { 249 | return main.getConfig().getString("Variables.TimeVariable.NightText"); 250 | } 251 | 252 | /* 253 | * WeatherVar 254 | */ 255 | public static String getRainText() { 256 | return main.getConfig().getString("Variables.WeatherVariable.RainText"); 257 | } 258 | 259 | public static String getSunText() { 260 | return main.getConfig().getString("Variables.WeatherVariable.SunText"); 261 | } 262 | 263 | public static String getWeatherWorld() { 264 | return main.getConfig().getString("Variables.WeatherVariable.World"); 265 | } 266 | 267 | /* 268 | * RandomNumberVar 269 | */ 270 | public static int getRandomMax() { 271 | return main.getConfig().getInt("Variables.RandomNumberVariable.Max"); 272 | } 273 | 274 | public static int getRandomMin() { 275 | return main.getConfig().getInt("Variables.RandomNumberVariable.Min"); 276 | } 277 | 278 | /* 279 | * RandomPlayerVar 280 | */ 281 | public static String getRandomPlayerVariableText() { 282 | return main.getConfig().getString("Variables.RandomPlayerVariable.UseTextWhenNobodyOnline.Text"); 283 | } 284 | 285 | public static boolean randomPlayerVariableUseTextEnabled() { 286 | return main.getConfig().getBoolean("Variables.RandomPlayerVariable.UseTextWhenNobodyOnline.Enable"); 287 | } 288 | 289 | public static boolean randomPlayerVariableUseDBEnabled() { 290 | return main.getConfig().getBoolean("Variables.RandomPlayerVariable.UseDatabaseNameWhenNobodyOnline.Enable"); 291 | } 292 | 293 | /* 294 | * ConfigSave 295 | */ 296 | 297 | public static int autoSaveIntervalInMin() { 298 | return main.getConfig().getInt("AutoSaveConfig.IntervalInMin"); 299 | } 300 | 301 | /* 302 | * SET BOOLEAN 303 | */ 304 | 305 | public static void toggleRestrictedMode(CommandSender sender) { 306 | if (SpigotConfig.restrictedModeEnabled()) { 307 | main.getConfig().set("RestrictedMode.Enable", false); 308 | sender.sendMessage("§e§oServerlist§6§lMOTD §7> §cRestrictedMode toggled off!"); 309 | } else { 310 | main.getConfig().set("RestrictedMode.Enable", true); 311 | sender.sendMessage("§e§oServerlist§6§lMOTD §7> §cRestrictedMode toggled on!"); 312 | 313 | for (Player p : Bukkit.getOnlinePlayers()) { 314 | if (!(p.isOp() || p.hasPermission("serverlist.restrictedmode.nokick"))) { 315 | p.kickPlayer(SpigotConfig.getRestrictedKickMessage()); 316 | } 317 | } 318 | } 319 | SpigotConfig.saveSmotdConfig(); 320 | } 321 | 322 | public static void toggleVersionText(CommandSender sender) { 323 | if (SpigotConfig.versionTextEnabled()) { 324 | main.getConfig().set("Slots.VersionText.Enable", false); 325 | sender.sendMessage("§e§oServerlist§6§lMOTD §7> §cVersionText toggled off!"); 326 | } else { 327 | main.getConfig().set("Slots.VersionText.Enable", true); 328 | sender.sendMessage("§e§oServerlist§6§lMOTD §7> §cVersionText toggled on!"); 329 | } 330 | SpigotConfig.saveSmotdConfig(); 331 | } 332 | 333 | public static void toggleRandomMotd(CommandSender sender) { 334 | if (SpigotConfig.randomMotdEnabled()) { 335 | main.getConfig().set("RandomMotd.Enable", false); 336 | sender.sendMessage("§e§oServerlist§6§lMOTD §7> §cRandomMotd toggled off!"); 337 | } else { 338 | main.getConfig().set("RandomMotd.Enable", true); 339 | sender.sendMessage("§e§oServerlist§6§lMOTD §7> §cRandomMotd toggled on!"); 340 | } 341 | SpigotConfig.saveSmotdConfig(); 342 | } 343 | 344 | public static void toggleBanMotd(CommandSender sender) { 345 | if (SpigotConfig.banMotdEnabled()) { 346 | main.getConfig().set("BanMotd.Enable", false); 347 | sender.sendMessage("§e§oServerlist§6§lMOTD §7> §cBanMotd toggled off!"); 348 | } else { 349 | main.getConfig().set("BanMotd.Enable", true); 350 | sender.sendMessage("§e§oServerlist§6§lMOTD §7> §cBanMotd toggled on!"); 351 | } 352 | SpigotConfig.saveSmotdConfig(); 353 | } 354 | 355 | public static void toggleWhitelistMotd(CommandSender sender) { 356 | if (SpigotConfig.whitelistMotdEnabled()) { 357 | main.getConfig().set("WhitelistMotd.Enable", false); 358 | sender.sendMessage("§e§oServerlist§6§lMOTD §7> §cWhitelistMotd toggled off!"); 359 | } else { 360 | main.getConfig().set("WhitelistMotd.Enable", true); 361 | sender.sendMessage("§e§oServerlist§6§lMOTD §7> §cWhitelistMotd toggled on!"); 362 | } 363 | SpigotConfig.saveSmotdConfig(); 364 | } 365 | 366 | public static void toggleHoverText(CommandSender sender) { 367 | if (SpigotConfig.hoverTextEnabled()) { 368 | main.getConfig().set("Slots.HoverText.Enable", false); 369 | sender.sendMessage("§e§oServerlist§6§lMOTD §7> §cHoverText toggled off!"); 370 | } else { 371 | main.getConfig().set("Slots.HoverText.Enable", true); 372 | sender.sendMessage("§e§oServerlist§6§lMOTD §7> §cHoverText toggled on!"); 373 | } 374 | SpigotConfig.saveSmotdConfig(); 375 | } 376 | 377 | public static void toggleUnknownSlots(CommandSender sender) { 378 | if (SpigotConfig.unknownSlotsEnabled()) { 379 | main.getConfig().set("Slots.UnknownSlots.Enable", false); 380 | sender.sendMessage("§e§oServerlist§6§lMOTD §7> §cUnknownSlots toggled off!"); 381 | } else { 382 | main.getConfig().set("Slots.UnknownSlots.Enable", true); 383 | sender.sendMessage("§e§oServerlist§6§lMOTD §7> §cUnknownSlots toggled on!"); 384 | } 385 | SpigotConfig.saveSmotdConfig(); 386 | } 387 | 388 | /* 389 | * UTIL 390 | */ 391 | 392 | /** 393 | * Reload config and inform MotdState of possible changes 394 | * @param sender Sender 395 | */ 396 | public static void reloadSmotdConfig(CommandSender sender) { 397 | main.reloadConfig(); 398 | sender.sendMessage("§e§oServerlist§6§lMOTD §7> §cConfig reloaded!"); 399 | MotdState.getInstance().initializeMotds(); 400 | } 401 | 402 | /** 403 | * Save config and inform MotdState of possible changes 404 | */ 405 | public static void saveSmotdConfig() { 406 | main.saveConfig(); 407 | MotdState.getInstance().initializeMotds(); 408 | } 409 | 410 | 411 | /** 412 | * Checks if world name set in config is existent 413 | * And fixes problems automatically 414 | */ 415 | public void configWorldCheck() { 416 | if (Bukkit.getWorld(getWeatherWorld()) == null || Bukkit.getWorld(getTimeWorld()) == null) { 417 | Bukkit.getLogger().info("------------------------"); 418 | //Informing user of mismatch 419 | Bukkit.getLogger().severe( 420 | "CAN'T FIND THE DEFINED WORLD FROM YOUR CONFIG!"); 421 | Bukkit.getLogger().info("Searching for available world..."); 422 | 423 | //Search shortest world name 424 | String worldName = ""; 425 | for(World w : Bukkit.getServer().getWorlds()) { 426 | if (worldName.equalsIgnoreCase("") | w.getName().length() < worldName.length()) { 427 | worldName = w.getName(); 428 | } 429 | } 430 | 431 | //If found world is not correct disable plugin and return 432 | if (Bukkit.getWorld(worldName) == null || Bukkit.getWorld(worldName) == null) { 433 | Bukkit.getPluginManager().disablePlugin(main); 434 | return; 435 | } 436 | 437 | //Update config with found world name 438 | main.getConfig().set("Variables.TimeVariable.World", worldName); 439 | main.getConfig().set("Variables.WeatherVariable.World", worldName); 440 | SpigotConfig.saveSmotdConfig(); 441 | Bukkit.getLogger().info("Found '" + worldName + "‘ and saved it to config."); 442 | Bukkit.getLogger().info("We're good now. ;-)"); 443 | Bukkit.getLogger().info("------------------------"); 444 | } 445 | } 446 | 447 | /** 448 | * Rename old config (if available) and write new one 449 | */ 450 | public static void migrateConfig() { 451 | if (!main.getConfig().isSet("DoNOTtouchMe") || main.getConfig().getDouble("DoNOTtouchMe") == 5.0) { 452 | File oldConfig = new File(main.getDataFolder(), "config.yml"); 453 | File newFile = new File(main.getDataFolder(), "config_old.yml"); 454 | 455 | if (newFile.exists()) { 456 | Bukkit.getLogger().severe("Remove your old config.yml!"); 457 | Bukkit.getPluginManager().disablePlugin(main); 458 | } 459 | 460 | boolean fileRenamed = oldConfig.renameTo(newFile); 461 | if (fileRenamed) { 462 | main.saveDefaultConfig(); 463 | main.reloadConfig(); 464 | Bukkit.getLogger().info("Renamed old config and created new config!"); 465 | } 466 | } 467 | if (main.getConfig().getDouble("DoNOTtouchMe") == 10.0) { 468 | Bukkit.getLogger().info("Adding new features to config.yml..."); 469 | main.getConfig().set("Slots.OutdatedClientText.Enable", false); 470 | main.getConfig().set("Slots.OutdatedClientText.Message", "Use Minecraft 1.16 &r&7%realonline%&8/&7%realslots%"); 471 | main.getConfig().set("DoNOTtouchMe", 10.1); 472 | saveSmotdConfig(); 473 | Bukkit.getLogger().info("Config successfully migrated to new version."); 474 | } 475 | } 476 | } 477 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ### Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0) License 2 | 3 | THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. 4 | 5 | BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS. 6 | 7 | 1. Definitions 8 | 9 | "Adaptation" means a work based upon the Work, or upon the Work and other pre-existing works, such as a translation, adaptation, derivative work, arrangement of music or other alterations of a literary or artistic work, or phonogram or performance and includes cinematographic adaptations or any other form in which the Work may be recast, transformed, or adapted including in any form recognizably derived from the original, except that a work that constitutes a Collection will not be considered an Adaptation for the purpose of this License. For the avoidance of doubt, where the Work is a musical work, performance or phonogram, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered an Adaptation for the purpose of this License. 10 | "Collection" means a collection of literary or artistic works, such as encyclopedias and anthologies, or performances, phonograms or broadcasts, or other works or subject matter other than works listed in Section 1(g) below, which, by reason of the selection and arrangement of their contents, constitute intellectual creations, in which the Work is included in its entirety in unmodified form along with one or more other contributions, each constituting separate and independent works in themselves, which together are assembled into a collective whole. A work that constitutes a Collection will not be considered an Adaptation (as defined above) for the purposes of this License. 11 | "Distribute" means to make available to the public the original and copies of the Work or Adaptation, as appropriate, through sale or other transfer of ownership. 12 | "License Elements" means the following high-level license attributes as selected by Licensor and indicated in the title of this License: Attribution, Noncommercial, ShareAlike. 13 | "Licensor" means the individual, individuals, entity or entities that offer(s) the Work under the terms of this License. 14 | "Original Author" means, in the case of a literary or artistic work, the individual, individuals, entity or entities who created the Work or if no individual or entity can be identified, the publisher; and in addition (i) in the case of a performance the actors, singers, musicians, dancers, and other persons who act, sing, deliver, declaim, play in, interpret or otherwise perform literary or artistic works or expressions of folklore; (ii) in the case of a phonogram the producer being the person or legal entity who first fixes the sounds of a performance or other sounds; and, (iii) in the case of broadcasts, the organization that transmits the broadcast. 15 | "Work" means the literary and/or artistic work offered under the terms of this License including without limitation any production in the literary, scientific and artistic domain, whatever may be the mode or form of its expression including digital form, such as a book, pamphlet and other writing; a lecture, address, sermon or other work of the same nature; a dramatic or dramatico-musical work; a choreographic work or entertainment in dumb show; a musical composition with or without words; a cinematographic work to which are assimilated works expressed by a process analogous to cinematography; a work of drawing, painting, architecture, sculpture, engraving or lithography; a photographic work to which are assimilated works expressed by a process analogous to photography; a work of applied art; an illustration, map, plan, sketch or three-dimensional work relative to geography, topography, architecture or science; a performance; a broadcast; a phonogram; a compilation of data to the extent it is protected as a copyrightable work; or a work performed by a variety or circus performer to the extent it is not otherwise considered a literary or artistic work. 16 | "You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation. 17 | "Publicly Perform" means to perform public recitations of the Work and to communicate to the public those public recitations, by any means or process, including by wire or wireless means or public digital performances; to make available to the public Works in such a way that members of the public may access these Works from a place and at a place individually chosen by them; to perform the Work to the public by any means or process and the communication to the public of the performances of the Work, including by public digital performance; to broadcast and rebroadcast the Work by any means including signs, sounds or images. 18 | "Reproduce" means to make copies of the Work by any means including without limitation by sound or visual recordings and the right of fixation and reproducing fixations of the Work, including storage of a protected performance or phonogram in digital form or other electronic medium. 19 | 2. Fair Dealing Rights. Nothing in this License is intended to reduce, limit, or restrict any uses free from copyright or rights arising from limitations or exceptions that are provided for in connection with the copyright protection under copyright law or other applicable laws. 20 | 21 | 3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below: 22 | 23 | to Reproduce the Work, to incorporate the Work into one or more Collections, and to Reproduce the Work as incorporated in the Collections; 24 | to create and Reproduce Adaptations provided that any such Adaptation, including any translation in any medium, takes reasonable steps to clearly label, demarcate or otherwise identify that changes were made to the original Work. For example, a translation could be marked "The original work was translated from English to Spanish," or a modification could indicate "The original work has been modified."; 25 | to Distribute and Publicly Perform the Work including as incorporated in Collections; and, 26 | to Distribute and Publicly Perform Adaptations. 27 | The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats. Subject to Section 8(f), all rights not expressly granted by Licensor are hereby reserved, including but not limited to the rights described in Section 4(e). 28 | 29 | 4. Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions: 30 | 31 | You may Distribute or Publicly Perform the Work only under the terms of this License. You must include a copy of, or the Uniform Resource Identifier (URI) for, this License with every copy of the Work You Distribute or Publicly Perform. You may not offer or impose any terms on the Work that restrict the terms of this License or the ability of the recipient of the Work to exercise the rights granted to that recipient under the terms of the License. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties with every copy of the Work You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Work, You may not impose any effective technological measures on the Work that restrict the ability of a recipient of the Work from You to exercise the rights granted to that recipient under the terms of the License. This Section 4(a) applies to the Work as incorporated in a Collection, but this does not require the Collection apart from the Work itself to be made subject to the terms of this License. If You create a Collection, upon notice from any Licensor You must, to the extent practicable, remove from the Collection any credit as required by Section 4(d), as requested. If You create an Adaptation, upon notice from any Licensor You must, to the extent practicable, remove from the Adaptation any credit as required by Section 4(d), as requested. 32 | You may Distribute or Publicly Perform an Adaptation only under: (i) the terms of this License; (ii) a later version of this License with the same License Elements as this License; (iii) a Creative Commons jurisdiction license (either this or a later license version) that contains the same License Elements as this License (e.g., Attribution-NonCommercial-ShareAlike 3.0 US) ("Applicable License"). You must include a copy of, or the URI, for Applicable License with every copy of each Adaptation You Distribute or Publicly Perform. You may not offer or impose any terms on the Adaptation that restrict the terms of the Applicable License or the ability of the recipient of the Adaptation to exercise the rights granted to that recipient under the terms of the Applicable License. You must keep intact all notices that refer to the Applicable License and to the disclaimer of warranties with every copy of the Work as included in the Adaptation You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Adaptation, You may not impose any effective technological measures on the Adaptation that restrict the ability of a recipient of the Adaptation from You to exercise the rights granted to that recipient under the terms of the Applicable License. This Section 4(b) applies to the Adaptation as incorporated in a Collection, but this does not require the Collection apart from the Adaptation itself to be made subject to the terms of the Applicable License. 33 | You may not exercise any of the rights granted to You in Section 3 above in any manner that is primarily intended for or directed toward commercial advantage or private monetary compensation. The exchange of the Work for other copyrighted works by means of digital file-sharing or otherwise shall not be considered to be intended for or directed toward commercial advantage or private monetary compensation, provided there is no payment of any monetary compensation in con-nection with the exchange of copyrighted works. 34 | If You Distribute, or Publicly Perform the Work or any Adaptations or Collections, You must, unless a request has been made pursuant to Section 4(a), keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or if the Original Author and/or Licensor designate another party or parties (e.g., a sponsor institute, publishing entity, journal) for attribution ("Attribution Parties") in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; (ii) the title of the Work if supplied; (iii) to the extent reasonably practicable, the URI, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and, (iv) consistent with Section 3(b), in the case of an Adaptation, a credit identifying the use of the Work in the Adaptation (e.g., "French translation of the Work by Original Author," or "Screenplay based on original Work by Original Author"). The credit required by this Section 4(d) may be implemented in any reasonable manner; provided, however, that in the case of a Adaptation or Collection, at a minimum such credit will appear, if a credit for all contributing authors of the Adaptation or Collection appears, then as part of these credits and in a manner at least as prominent as the credits for the other contributing authors. For the avoidance of doubt, You may only use the credit required by this Section for the purpose of attribution in the manner set out above and, by exercising Your rights under this License, You may not implicitly or explicitly assert or imply any connection with, sponsorship or endorsement by the Original Author, Licensor and/or Attribution Parties, as appropriate, of You or Your use of the Work, without the separate, express prior written permission of the Original Author, Licensor and/or Attribution Parties. 35 | For the avoidance of doubt: 36 | 37 | Non-waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme cannot be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License; 38 | Waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme can be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License if Your exercise of such rights is for a purpose or use which is otherwise than noncommercial as permitted under Section 4(c) and otherwise waives the right to collect royalties through any statutory or compulsory licensing scheme; and, 39 | Voluntary License Schemes. The Licensor reserves the right to collect royalties, whether individually or, in the event that the Licensor is a member of a collecting society that administers voluntary licensing schemes, via that society, from any exercise by You of the rights granted under this License that is for a purpose or use which is otherwise than noncommercial as permitted under Section 4(c). 40 | Except as otherwise agreed in writing by the Licensor or as may be otherwise permitted by applicable law, if You Reproduce, Distribute or Publicly Perform the Work either by itself or as part of any Adaptations or Collections, You must not distort, mutilate, modify or take other derogatory action in relation to the Work which would be prejudicial to the Original Author's honor or reputation. Licensor agrees that in those jurisdictions (e.g. Japan), in which any exercise of the right granted in Section 3(b) of this License (the right to make Adaptations) would be deemed to be a distortion, mutilation, modification or other derogatory action prejudicial to the Original Author's honor and reputation, the Licensor will waive or not assert, as appropriate, this Section, to the fullest extent permitted by the applicable national law, to enable You to reasonably exercise Your right under Section 3(b) of this License (right to make Adaptations) but not otherwise. 41 | 5. Representations, Warranties and Disclaimer 42 | 43 | UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING AND TO THE FULLEST EXTENT PERMITTED BY APPLICABLE LAW, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO THIS EXCLUSION MAY NOT APPLY TO YOU. 44 | 45 | 6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 46 | 47 | 7. Termination 48 | 49 | This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Adaptations or Collections from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License. 50 | Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above. 51 | 8. Miscellaneous 52 | 53 | Each time You Distribute or Publicly Perform the Work or a Collection, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License. 54 | Each time You Distribute or Publicly Perform an Adaptation, Licensor offers to the recipient a license to the original Work on the same terms and conditions as the license granted to You under this License. 55 | If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. 56 | No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent. 57 | This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You. 58 | The rights granted under, and the subject matter referenced, in this License were drafted utilizing the terminology of the Berne Convention for the Protection of Literary and Artistic Works (as amended on September 28, 1979), the Rome Convention of 1961, the WIPO Copyright Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 and the Universal Copyright Convention (as revised on July 24, 1971). These rights and subject matter take effect in the relevant jurisdiction in which the License terms are sought to be enforced according to the corresponding provisions of the implementation of those treaty provisions in the applicable national law. If the standard suite of rights granted under applicable copyright law includes additional rights not granted under this License, such additional rights are deemed to be included in the License; this License is not intended to restrict the license of any rights under applicable law. 59 | 60 | More at https://creativecommons.org/licenses/by-nc-sa/3.0/ 61 | --------------------------------------------------------------------------------