add locales

This commit is contained in:
okx-code
2018-11-27 17:14:11 +00:00
parent c90dccee0d
commit 861644566d
8 changed files with 313 additions and 548 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ plugins {
}
group 'sh.okx'
version '3.3.1'
version '3.3.2-beta'
repositories {
mavenCentral()
+248 -479
View File
@@ -2,26 +2,21 @@ package sh.okx.rankup;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.ServicePriority;
import org.bukkit.plugin.java.JavaPlugin;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import javax.net.ssl.HttpsURLConnection;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.zip.GZIPOutputStream;
@@ -30,22 +25,46 @@ import java.util.zip.GZIPOutputStream;
* <p>
* Check out https://bStats.org/ to learn more about bStats!
*/
@SuppressWarnings({"WeakerAccess", "unused"})
public class Metrics {
static {
// You can use the property to disable the check in your test environment
if (System.getProperty("bstats.relocatecheck") == null || !System.getProperty("bstats.relocatecheck").equals("false")) {
// Maven's Relocate is clever and changes strings, too. So we have to use this little "trick" ... :D
final String defaultPackage = new String(
new byte[]{'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's', '.', 'b', 'u', 'k', 'k', 'i', 't'});
final String examplePackage = new String(new byte[]{'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'});
// We want to make sure nobody just copy & pastes the example and use the wrong package names
if (Metrics.class.getPackage().getName().equals(defaultPackage) || Metrics.class.getPackage().getName().equals(examplePackage)) {
throw new IllegalStateException("bStats Metrics class has not been relocated correctly!");
}
}
}
// The version of this bStats class
public static final int B_STATS_VERSION = 1;
// The url to which the data is sent
private static final String URL = "https://bStats.org/submitData";
private static final String URL = "https://bStats.org/submitData/bukkit";
// Is bStats enabled on this server?
private boolean enabled;
// Should failed requests be logged?
private static boolean logFailedRequests;
// Should the sent data be logged?
private static boolean logSentData;
// Should the response text be logged?
private static boolean logResponseStatusText;
// The uuid of the server
private static String serverUUID;
// The plugin
private final JavaPlugin plugin;
private final Plugin plugin;
// A list with all custom charts
private final List<CustomChart> charts = new ArrayList<>();
@@ -55,7 +74,7 @@ public class Metrics {
*
* @param plugin The plugin which stats should be submitted.
*/
public Metrics(JavaPlugin plugin) {
public Metrics(Plugin plugin) {
if (plugin == null) {
throw new IllegalArgumentException("Plugin cannot be null!");
}
@@ -75,6 +94,10 @@ public class Metrics {
config.addDefault("serverUuid", UUID.randomUUID().toString());
// Should failed request be logged?
config.addDefault("logFailedRequests", false);
// Should the sent data be logged?
config.addDefault("logSentData", false);
// Should the response text be logged?
config.addDefault("logResponseStatusText", false);
// Inform the server owners about bStats
config.options().header(
@@ -85,14 +108,17 @@ public class Metrics {
).copyDefaults(true);
try {
config.save(configFile);
} catch (IOException ignored) {
}
} catch (IOException ignored) { }
}
// Load the data
enabled = config.getBoolean("enabled", true);
serverUUID = config.getString("serverUuid");
logFailedRequests = config.getBoolean("logFailedRequests", false);
if (config.getBoolean("enabled", true)) {
logSentData = config.getBoolean("logSentData", false);
logResponseStatusText = config.getBoolean("logResponseStatusText", false);
if (enabled) {
boolean found = false;
// Search for all other bStats Metrics classes to see if we are the first one
for (Class<?> service : Bukkit.getServicesManager().getKnownServices()) {
@@ -100,8 +126,7 @@ public class Metrics {
service.getField("B_STATS_VERSION"); // Our identifier :)
found = true; // We aren't the first
break;
} catch (NoSuchFieldException ignored) {
}
} catch (NoSuchFieldException ignored) { }
}
// Register our service
Bukkit.getServicesManager().register(Metrics.class, this, plugin, ServicePriority.Normal);
@@ -113,58 +138,12 @@ public class Metrics {
}
/**
* Sends the data to the bStats server.
* Checks if bStats is enabled.
*
* @param data The data to send.
* @throws Exception If the request failed.
* @return Whether bStats is enabled or not.
*/
private static void sendData(JSONObject data) throws Exception {
if (data == null) {
throw new IllegalArgumentException("Data cannot be null!");
}
if (Bukkit.isPrimaryThread()) {
throw new IllegalAccessException("This method must not be called from the main thread!");
}
HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection();
// Compress the data to save bandwidth
byte[] compressedData = compress(data.toString());
// Add headers
connection.setRequestMethod("POST");
connection.addRequestProperty("Accept", "application/json");
connection.addRequestProperty("Connection", "close");
connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request
connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length));
connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format
connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION);
// Send data
connection.setDoOutput(true);
DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
outputStream.write(compressedData);
outputStream.flush();
outputStream.close();
connection.getInputStream().close(); // We don't care about the response - Just send our data :)
}
/**
* Gzips the given String.
*
* @param str The string to gzip.
* @return The gzipped String.
* @throws IOException If the compression failed.
*/
private static byte[] compress(final String str) throws IOException {
if (str == null) {
return null;
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
GZIPOutputStream gzip = new GZIPOutputStream(outputStream);
gzip.write(str.getBytes("UTF-8"));
gzip.close();
return outputStream.toByteArray();
public boolean isEnabled() {
return enabled;
}
/**
@@ -193,12 +172,7 @@ public class Metrics {
}
// Nevertheless we want our code to run in the Bukkit main thread, so we have to use the Bukkit scheduler
// Don't be afraid! The connection to the bStats server is still async, only the stats collection is sync ;)
Bukkit.getScheduler().runTask(plugin, new Runnable() {
@Override
public void run() {
submitData();
}
});
Bukkit.getScheduler().runTask(plugin, () -> submitData());
}
}, 1000 * 60 * 5, 1000 * 60 * 30);
// Submit the data every 30 minutes, first time after 5 minutes to give other plugins enough time to start
@@ -241,10 +215,19 @@ public class Metrics {
*/
private JSONObject getServerData() {
// Minecraft specific data
int playerAmount = Bukkit.getOnlinePlayers().size();
int playerAmount;
try {
// Around MC 1.8 the return type was changed to a collection from an array,
// This fixes java.lang.NoSuchMethodError: org.bukkit.Bukkit.getOnlinePlayers()Ljava/util/Collection;
Method onlinePlayersMethod = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers");
playerAmount = onlinePlayersMethod.getReturnType().equals(Collection.class)
? ((Collection<?>) onlinePlayersMethod.invoke(Bukkit.getServer())).size()
: ((Player[]) onlinePlayersMethod.invoke(Bukkit.getServer())).length;
} catch (Exception e) {
playerAmount = Bukkit.getOnlinePlayers().size(); // Just use the new method if the Reflection failed
}
int onlineMode = Bukkit.getOnlineMode() ? 1 : 0;
String bukkitVersion = org.bukkit.Bukkit.getVersion();
bukkitVersion = bukkitVersion.substring(bukkitVersion.indexOf("MC: ") + 4, bukkitVersion.length() - 1);
String bukkitVersion = Bukkit.getVersion();
// OS/Java specific data
String javaVersion = System.getProperty("java.version");
@@ -281,14 +264,13 @@ public class Metrics {
for (Class<?> service : Bukkit.getServicesManager().getKnownServices()) {
try {
service.getField("B_STATS_VERSION"); // Our identifier :)
} catch (NoSuchFieldException ignored) {
continue; // Continue "searching"
}
// Found one!
try {
pluginData.add(service.getMethod("getPluginData").invoke(Bukkit.getServicesManager().load(service)));
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) {
}
for (RegisteredServiceProvider<?> provider : Bukkit.getServicesManager().getRegistrations(service)) {
try {
pluginData.add(provider.getService().getMethod("getPluginData").invoke(provider.getProvider()));
} catch (NullPointerException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) { }
}
} catch (NoSuchFieldException ignored) { }
}
data.put("plugins", pluginData);
@@ -299,7 +281,7 @@ public class Metrics {
public void run() {
try {
// Send the data
sendData(data);
sendData(plugin, data);
} catch (Exception e) {
// Something went wrong! :(
if (logFailedRequests) {
@@ -308,322 +290,76 @@ public class Metrics {
}
}
}).start();
}
/**
* A enum which is used for custom maps.
* Sends the data to the bStats server.
*
* @param plugin Any plugin. It's just used to get a logger instance.
* @param data The data to send.
* @throws Exception If the request failed.
*/
public enum Country {
/**
* bStats will use the country of the server.
*/
AUTO_DETECT("AUTO", "Auto Detected"),
ANDORRA("AD", "Andorra"),
UNITED_ARAB_EMIRATES("AE", "United Arab Emirates"),
AFGHANISTAN("AF", "Afghanistan"),
ANTIGUA_AND_BARBUDA("AG", "Antigua and Barbuda"),
ANGUILLA("AI", "Anguilla"),
ALBANIA("AL", "Albania"),
ARMENIA("AM", "Armenia"),
NETHERLANDS_ANTILLES("AN", "Netherlands Antilles"),
ANGOLA("AO", "Angola"),
ANTARCTICA("AQ", "Antarctica"),
ARGENTINA("AR", "Argentina"),
AMERICAN_SAMOA("AS", "American Samoa"),
AUSTRIA("AT", "Austria"),
AUSTRALIA("AU", "Australia"),
ARUBA("AW", "Aruba"),
ÅLAND_ISLANDS("AX", "Åland Islands"),
AZERBAIJAN("AZ", "Azerbaijan"),
BOSNIA_AND_HERZEGOVINA("BA", "Bosnia and Herzegovina"),
BARBADOS("BB", "Barbados"),
BANGLADESH("BD", "Bangladesh"),
BELGIUM("BE", "Belgium"),
BURKINA_FASO("BF", "Burkina Faso"),
BULGARIA("BG", "Bulgaria"),
BAHRAIN("BH", "Bahrain"),
BURUNDI("BI", "Burundi"),
BENIN("BJ", "Benin"),
SAINT_BARTHÉLEMY("BL", "Saint Barthélemy"),
BERMUDA("BM", "Bermuda"),
BRUNEI("BN", "Brunei"),
BOLIVIA("BO", "Bolivia"),
BONAIRE_SINT_EUSTATIUS_AND_SABA("BQ", "Bonaire, Sint Eustatius and Saba"),
BRAZIL("BR", "Brazil"),
BAHAMAS("BS", "Bahamas"),
BHUTAN("BT", "Bhutan"),
BOUVET_ISLAND("BV", "Bouvet Island"),
BOTSWANA("BW", "Botswana"),
BELARUS("BY", "Belarus"),
BELIZE("BZ", "Belize"),
CANADA("CA", "Canada"),
COCOS_ISLANDS("CC", "Cocos Islands"),
THE_DEMOCRATIC_REPUBLIC_OF_CONGO("CD", "The Democratic Republic Of Congo"),
CENTRAL_AFRICAN_REPUBLIC("CF", "Central African Republic"),
CONGO("CG", "Congo"),
SWITZERLAND("CH", "Switzerland"),
CÔTE_D_IVOIRE("CI", "Côte d'Ivoire"),
COOK_ISLANDS("CK", "Cook Islands"),
CHILE("CL", "Chile"),
CAMEROON("CM", "Cameroon"),
CHINA("CN", "China"),
COLOMBIA("CO", "Colombia"),
COSTA_RICA("CR", "Costa Rica"),
CUBA("CU", "Cuba"),
CAPE_VERDE("CV", "Cape Verde"),
CURAÇAO("CW", "Curaçao"),
CHRISTMAS_ISLAND("CX", "Christmas Island"),
CYPRUS("CY", "Cyprus"),
CZECH_REPUBLIC("CZ", "Czech Republic"),
GERMANY("DE", "Germany"),
DJIBOUTI("DJ", "Djibouti"),
DENMARK("DK", "Denmark"),
DOMINICA("DM", "Dominica"),
DOMINICAN_REPUBLIC("DO", "Dominican Republic"),
ALGERIA("DZ", "Algeria"),
ECUADOR("EC", "Ecuador"),
ESTONIA("EE", "Estonia"),
EGYPT("EG", "Egypt"),
WESTERN_SAHARA("EH", "Western Sahara"),
ERITREA("ER", "Eritrea"),
SPAIN("ES", "Spain"),
ETHIOPIA("ET", "Ethiopia"),
FINLAND("FI", "Finland"),
FIJI("FJ", "Fiji"),
FALKLAND_ISLANDS("FK", "Falkland Islands"),
MICRONESIA("FM", "Micronesia"),
FAROE_ISLANDS("FO", "Faroe Islands"),
FRANCE("FR", "France"),
GABON("GA", "Gabon"),
UNITED_KINGDOM("GB", "United Kingdom"),
GRENADA("GD", "Grenada"),
GEORGIA("GE", "Georgia"),
FRENCH_GUIANA("GF", "French Guiana"),
GUERNSEY("GG", "Guernsey"),
GHANA("GH", "Ghana"),
GIBRALTAR("GI", "Gibraltar"),
GREENLAND("GL", "Greenland"),
GAMBIA("GM", "Gambia"),
GUINEA("GN", "Guinea"),
GUADELOUPE("GP", "Guadeloupe"),
EQUATORIAL_GUINEA("GQ", "Equatorial Guinea"),
GREECE("GR", "Greece"),
SOUTH_GEORGIA_AND_THE_SOUTH_SANDWICH_ISLANDS("GS", "South Georgia And The South Sandwich Islands"),
GUATEMALA("GT", "Guatemala"),
GUAM("GU", "Guam"),
GUINEA_BISSAU("GW", "Guinea-Bissau"),
GUYANA("GY", "Guyana"),
HONG_KONG("HK", "Hong Kong"),
HEARD_ISLAND_AND_MCDONALD_ISLANDS("HM", "Heard Island And McDonald Islands"),
HONDURAS("HN", "Honduras"),
CROATIA("HR", "Croatia"),
HAITI("HT", "Haiti"),
HUNGARY("HU", "Hungary"),
INDONESIA("ID", "Indonesia"),
IRELAND("IE", "Ireland"),
ISRAEL("IL", "Israel"),
ISLE_OF_MAN("IM", "Isle Of Man"),
INDIA("IN", "India"),
BRITISH_INDIAN_OCEAN_TERRITORY("IO", "British Indian Ocean Territory"),
IRAQ("IQ", "Iraq"),
IRAN("IR", "Iran"),
ICELAND("IS", "Iceland"),
ITALY("IT", "Italy"),
JERSEY("JE", "Jersey"),
JAMAICA("JM", "Jamaica"),
JORDAN("JO", "Jordan"),
JAPAN("JP", "Japan"),
KENYA("KE", "Kenya"),
KYRGYZSTAN("KG", "Kyrgyzstan"),
CAMBODIA("KH", "Cambodia"),
KIRIBATI("KI", "Kiribati"),
COMOROS("KM", "Comoros"),
SAINT_KITTS_AND_NEVIS("KN", "Saint Kitts And Nevis"),
NORTH_KOREA("KP", "North Korea"),
SOUTH_KOREA("KR", "South Korea"),
KUWAIT("KW", "Kuwait"),
CAYMAN_ISLANDS("KY", "Cayman Islands"),
KAZAKHSTAN("KZ", "Kazakhstan"),
LAOS("LA", "Laos"),
LEBANON("LB", "Lebanon"),
SAINT_LUCIA("LC", "Saint Lucia"),
LIECHTENSTEIN("LI", "Liechtenstein"),
SRI_LANKA("LK", "Sri Lanka"),
LIBERIA("LR", "Liberia"),
LESOTHO("LS", "Lesotho"),
LITHUANIA("LT", "Lithuania"),
LUXEMBOURG("LU", "Luxembourg"),
LATVIA("LV", "Latvia"),
LIBYA("LY", "Libya"),
MOROCCO("MA", "Morocco"),
MONACO("MC", "Monaco"),
MOLDOVA("MD", "Moldova"),
MONTENEGRO("ME", "Montenegro"),
SAINT_MARTIN("MF", "Saint Martin"),
MADAGASCAR("MG", "Madagascar"),
MARSHALL_ISLANDS("MH", "Marshall Islands"),
MACEDONIA("MK", "Macedonia"),
MALI("ML", "Mali"),
MYANMAR("MM", "Myanmar"),
MONGOLIA("MN", "Mongolia"),
MACAO("MO", "Macao"),
NORTHERN_MARIANA_ISLANDS("MP", "Northern Mariana Islands"),
MARTINIQUE("MQ", "Martinique"),
MAURITANIA("MR", "Mauritania"),
MONTSERRAT("MS", "Montserrat"),
MALTA("MT", "Malta"),
MAURITIUS("MU", "Mauritius"),
MALDIVES("MV", "Maldives"),
MALAWI("MW", "Malawi"),
MEXICO("MX", "Mexico"),
MALAYSIA("MY", "Malaysia"),
MOZAMBIQUE("MZ", "Mozambique"),
NAMIBIA("NA", "Namibia"),
NEW_CALEDONIA("NC", "New Caledonia"),
NIGER("NE", "Niger"),
NORFOLK_ISLAND("NF", "Norfolk Island"),
NIGERIA("NG", "Nigeria"),
NICARAGUA("NI", "Nicaragua"),
NETHERLANDS("NL", "Netherlands"),
NORWAY("NO", "Norway"),
NEPAL("NP", "Nepal"),
NAURU("NR", "Nauru"),
NIUE("NU", "Niue"),
NEW_ZEALAND("NZ", "New Zealand"),
OMAN("OM", "Oman"),
PANAMA("PA", "Panama"),
PERU("PE", "Peru"),
FRENCH_POLYNESIA("PF", "French Polynesia"),
PAPUA_NEW_GUINEA("PG", "Papua New Guinea"),
PHILIPPINES("PH", "Philippines"),
PAKISTAN("PK", "Pakistan"),
POLAND("PL", "Poland"),
SAINT_PIERRE_AND_MIQUELON("PM", "Saint Pierre And Miquelon"),
PITCAIRN("PN", "Pitcairn"),
PUERTO_RICO("PR", "Puerto Rico"),
PALESTINE("PS", "Palestine"),
PORTUGAL("PT", "Portugal"),
PALAU("PW", "Palau"),
PARAGUAY("PY", "Paraguay"),
QATAR("QA", "Qatar"),
REUNION("RE", "Reunion"),
ROMANIA("RO", "Romania"),
SERBIA("RS", "Serbia"),
RUSSIA("RU", "Russia"),
RWANDA("RW", "Rwanda"),
SAUDI_ARABIA("SA", "Saudi Arabia"),
SOLOMON_ISLANDS("SB", "Solomon Islands"),
SEYCHELLES("SC", "Seychelles"),
SUDAN("SD", "Sudan"),
SWEDEN("SE", "Sweden"),
SINGAPORE("SG", "Singapore"),
SAINT_HELENA("SH", "Saint Helena"),
SLOVENIA("SI", "Slovenia"),
SVALBARD_AND_JAN_MAYEN("SJ", "Svalbard And Jan Mayen"),
SLOVAKIA("SK", "Slovakia"),
SIERRA_LEONE("SL", "Sierra Leone"),
SAN_MARINO("SM", "San Marino"),
SENEGAL("SN", "Senegal"),
SOMALIA("SO", "Somalia"),
SURINAME("SR", "Suriname"),
SOUTH_SUDAN("SS", "South Sudan"),
SAO_TOME_AND_PRINCIPE("ST", "Sao Tome And Principe"),
EL_SALVADOR("SV", "El Salvador"),
SINT_MAARTEN_DUTCH_PART("SX", "Sint Maarten (Dutch part)"),
SYRIA("SY", "Syria"),
SWAZILAND("SZ", "Swaziland"),
TURKS_AND_CAICOS_ISLANDS("TC", "Turks And Caicos Islands"),
CHAD("TD", "Chad"),
FRENCH_SOUTHERN_TERRITORIES("TF", "French Southern Territories"),
TOGO("TG", "Togo"),
THAILAND("TH", "Thailand"),
TAJIKISTAN("TJ", "Tajikistan"),
TOKELAU("TK", "Tokelau"),
TIMOR_LESTE("TL", "Timor-Leste"),
TURKMENISTAN("TM", "Turkmenistan"),
TUNISIA("TN", "Tunisia"),
TONGA("TO", "Tonga"),
TURKEY("TR", "Turkey"),
TRINIDAD_AND_TOBAGO("TT", "Trinidad and Tobago"),
TUVALU("TV", "Tuvalu"),
TAIWAN("TW", "Taiwan"),
TANZANIA("TZ", "Tanzania"),
UKRAINE("UA", "Ukraine"),
UGANDA("UG", "Uganda"),
UNITED_STATES_MINOR_OUTLYING_ISLANDS("UM", "United States Minor Outlying Islands"),
UNITED_STATES("US", "United States"),
URUGUAY("UY", "Uruguay"),
UZBEKISTAN("UZ", "Uzbekistan"),
VATICAN("VA", "Vatican"),
SAINT_VINCENT_AND_THE_GRENADINES("VC", "Saint Vincent And The Grenadines"),
VENEZUELA("VE", "Venezuela"),
BRITISH_VIRGIN_ISLANDS("VG", "British Virgin Islands"),
U_S__VIRGIN_ISLANDS("VI", "U.S. Virgin Islands"),
VIETNAM("VN", "Vietnam"),
VANUATU("VU", "Vanuatu"),
WALLIS_AND_FUTUNA("WF", "Wallis And Futuna"),
SAMOA("WS", "Samoa"),
YEMEN("YE", "Yemen"),
MAYOTTE("YT", "Mayotte"),
SOUTH_AFRICA("ZA", "South Africa"),
ZAMBIA("ZM", "Zambia"),
ZIMBABWE("ZW", "Zimbabwe");
private String isoTag;
private String name;
Country(String isoTag, String name) {
this.isoTag = isoTag;
this.name = name;
private static void sendData(Plugin plugin, JSONObject data) throws Exception {
if (data == null) {
throw new IllegalArgumentException("Data cannot be null!");
}
if (Bukkit.isPrimaryThread()) {
throw new IllegalAccessException("This method must not be called from the main thread!");
}
if (logSentData) {
plugin.getLogger().info("Sending data to bStats: " + data.toString());
}
HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection();
/**
* Gets a country by it's iso tag.
*
* @param isoTag The iso tag of the county.
* @return The country with the given iso tag or <code>null</code> if unknown.
*/
public static Country byIsoTag(String isoTag) {
for (Country country : Country.values()) {
if (country.getCountryIsoTag().equals(isoTag)) {
return country;
}
}
// Compress the data to save bandwidth
byte[] compressedData = compress(data.toString());
// Add headers
connection.setRequestMethod("POST");
connection.addRequestProperty("Accept", "application/json");
connection.addRequestProperty("Connection", "close");
connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request
connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length));
connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format
connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION);
// Send data
connection.setDoOutput(true);
DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
outputStream.write(compressedData);
outputStream.flush();
outputStream.close();
InputStream inputStream = connection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder builder = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
builder.append(line);
}
bufferedReader.close();
if (logResponseStatusText) {
plugin.getLogger().info("Sent data to bStats and received response: " + builder.toString());
}
}
/**
* Gzips the given String.
*
* @param str The string to gzip.
* @return The gzipped String.
* @throws IOException If the compression failed.
*/
private static byte[] compress(final String str) throws IOException {
if (str == null) {
return null;
}
/**
* Gets a country by a locale.
*
* @param locale The locale.
* @return The country from the giben locale or <code>null</code> if unknown country or
* if the locale does not contain a country.
*/
public static Country byLocale(Locale locale) {
return byIsoTag(locale.getCountry());
}
/**
* Gets the name of the country.
*
* @return The name of the country.
*/
public String getCountryName() {
return name;
}
/**
* Gets the iso tag of the country.
*
* @return The iso tag of the country.
*/
public String getCountryIsoTag() {
return isoTag;
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
GZIPOutputStream gzip = new GZIPOutputStream(outputStream);
gzip.write(str.getBytes(StandardCharsets.UTF_8));
gzip.close();
return outputStream.toByteArray();
}
/**
@@ -632,21 +368,21 @@ public class Metrics {
public static abstract class CustomChart {
// The id of the chart
protected final String chartId;
final String chartId;
/**
* Class constructor.
*
* @param chartId The id of the chart.
*/
public CustomChart(String chartId) {
CustomChart(String chartId) {
if (chartId == null || chartId.isEmpty()) {
throw new IllegalArgumentException("ChartId cannot be null or empty!");
}
this.chartId = chartId;
}
protected JSONObject getRequestJsonObject() {
private JSONObject getRequestJsonObject() {
JSONObject chart = new JSONObject();
chart.put("chartId", chartId);
try {
@@ -665,35 +401,32 @@ public class Metrics {
return chart;
}
protected abstract JSONObject getChartData();
protected abstract JSONObject getChartData() throws Exception;
}
/**
* Represents a custom simple pie.
*/
public static abstract class SimplePie extends CustomChart {
public static class SimplePie extends CustomChart {
private final Callable<String> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SimplePie(String chartId) {
public SimplePie(String chartId, Callable<String> callable) {
super(chartId);
this.callable = callable;
}
/**
* Gets the value of the pie.
*
* @return The value of the pie.
*/
public abstract String getValue();
@Override
protected JSONObject getChartData() {
protected JSONObject getChartData() throws Exception {
JSONObject data = new JSONObject();
String value = getValue();
String value = callable.call();
if (value == null || value.isEmpty()) {
// Null = skip the chart
return null;
@@ -706,31 +439,26 @@ public class Metrics {
/**
* Represents a custom advanced pie.
*/
public static abstract class AdvancedPie extends CustomChart {
public static class AdvancedPie extends CustomChart {
private final Callable<Map<String, Integer>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public AdvancedPie(String chartId) {
public AdvancedPie(String chartId, Callable<Map<String, Integer>> callable) {
super(chartId);
this.callable = callable;
}
/**
* Gets the values of the pie.
*
* @param valueMap Just an empty map. The only reason it exists is to make your life easier.
* You don't have to create a map yourself!
* @return The values of the pie.
*/
public abstract HashMap<String, Integer> getValues(HashMap<String, Integer> valueMap);
@Override
protected JSONObject getChartData() {
protected JSONObject getChartData() throws Exception {
JSONObject data = new JSONObject();
JSONObject values = new JSONObject();
HashMap<String, Integer> map = getValues(new HashMap<String, Integer>());
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
@@ -753,30 +481,76 @@ public class Metrics {
}
/**
* Represents a custom single line chart.
* Represents a custom drilldown pie.
*/
public static abstract class SingleLineChart extends CustomChart {
public static class DrilldownPie extends CustomChart {
private final Callable<Map<String, Map<String, Integer>>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SingleLineChart(String chartId) {
public DrilldownPie(String chartId, Callable<Map<String, Map<String, Integer>>> callable) {
super(chartId);
this.callable = callable;
}
@Override
public JSONObject getChartData() throws Exception {
JSONObject data = new JSONObject();
JSONObject values = new JSONObject();
Map<String, Map<String, Integer>> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean reallyAllSkipped = true;
for (Map.Entry<String, Map<String, Integer>> entryValues : map.entrySet()) {
JSONObject value = new JSONObject();
boolean allSkipped = true;
for (Map.Entry<String, Integer> valueEntry : map.get(entryValues.getKey()).entrySet()) {
value.put(valueEntry.getKey(), valueEntry.getValue());
allSkipped = false;
}
if (!allSkipped) {
reallyAllSkipped = false;
values.put(entryValues.getKey(), value);
}
}
if (reallyAllSkipped) {
// Null = skip the chart
return null;
}
data.put("values", values);
return data;
}
}
/**
* Represents a custom single line chart.
*/
public static class SingleLineChart extends CustomChart {
private final Callable<Integer> callable;
/**
* Gets the value of the chart.
* Class constructor.
*
* @return The value of the chart.
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public abstract int getValue();
public SingleLineChart(String chartId, Callable<Integer> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JSONObject getChartData() {
protected JSONObject getChartData() throws Exception {
JSONObject data = new JSONObject();
int value = getValue();
int value = callable.call();
if (value == 0) {
// Null = skip the chart
return null;
@@ -790,31 +564,26 @@ public class Metrics {
/**
* Represents a custom multi line chart.
*/
public static abstract class MultiLineChart extends CustomChart {
public static class MultiLineChart extends CustomChart {
private final Callable<Map<String, Integer>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public MultiLineChart(String chartId) {
public MultiLineChart(String chartId, Callable<Map<String, Integer>> callable) {
super(chartId);
this.callable = callable;
}
/**
* Gets the values of the chart.
*
* @param valueMap Just an empty map. The only reason it exists is to make your life easier.
* You don't have to create a map yourself!
* @return The values of the chart.
*/
public abstract HashMap<String, Integer> getValues(HashMap<String, Integer> valueMap);
@Override
protected JSONObject getChartData() {
protected JSONObject getChartData() throws Exception {
JSONObject data = new JSONObject();
JSONObject values = new JSONObject();
HashMap<String, Integer> map = getValues(new HashMap<String, Integer>());
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
@@ -838,80 +607,81 @@ public class Metrics {
}
/**
* Represents a custom simple map chart.
* Represents a custom simple bar chart.
*/
public static abstract class SimpleMapChart extends CustomChart {
public static class SimpleBarChart extends CustomChart {
private final Callable<Map<String, Integer>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SimpleMapChart(String chartId) {
public SimpleBarChart(String chartId, Callable<Map<String, Integer>> callable) {
super(chartId);
this.callable = callable;
}
/**
* Gets the value of the chart.
*
* @return The value of the chart.
*/
public abstract Country getValue();
@Override
protected JSONObject getChartData() {
protected JSONObject getChartData() throws Exception {
JSONObject data = new JSONObject();
Country value = getValue();
if (value == null) {
JSONObject values = new JSONObject();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
data.put("value", value.getCountryIsoTag());
for (Map.Entry<String, Integer> entry : map.entrySet()) {
JSONArray categoryValues = new JSONArray();
categoryValues.add(entry.getValue());
values.put(entry.getKey(), categoryValues);
}
data.put("values", values);
return data;
}
}
/**
* Represents a custom advanced map chart.
* Represents a custom advanced bar chart.
*/
public static abstract class AdvancedMapChart extends CustomChart {
public static class AdvancedBarChart extends CustomChart {
private final Callable<Map<String, int[]>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public AdvancedMapChart(String chartId) {
public AdvancedBarChart(String chartId, Callable<Map<String, int[]>> callable) {
super(chartId);
this.callable = callable;
}
/**
* Gets the value of the chart.
*
* @param valueMap Just an empty map. The only reason it exists is to make your life easier.
* You don't have to create a map yourself!
* @return The value of the chart.
*/
public abstract HashMap<Country, Integer> getValues(HashMap<Country, Integer> valueMap);
@Override
protected JSONObject getChartData() {
protected JSONObject getChartData() throws Exception {
JSONObject data = new JSONObject();
JSONObject values = new JSONObject();
HashMap<Country, Integer> map = getValues(new HashMap<Country, Integer>());
Map<String, int[]> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean allSkipped = true;
for (Map.Entry<Country, Integer> entry : map.entrySet()) {
if (entry.getValue() == 0) {
for (Map.Entry<String, int[]> entry : map.entrySet()) {
if (entry.getValue().length == 0) {
continue; // Skip this invalid
}
allSkipped = false;
values.put(entry.getKey().getCountryIsoTag(), entry.getValue());
JSONArray categoryValues = new JSONArray();
for (int categoryValue : entry.getValue()) {
categoryValues.add(categoryValue);
}
values.put(entry.getKey(), categoryValues);
}
if (allSkipped) {
// Null = skip the chart
@@ -920,7 +690,6 @@ public class Metrics {
data.put("values", values);
return data;
}
}
}
+50 -26
View File
@@ -1,6 +1,7 @@
package sh.okx.rankup;
import com.gmail.nossr50.datatypes.skills.SkillType;
import com.google.common.base.Preconditions;
import lombok.Getter;
import net.milkbowl.vault.economy.Economy;
import net.milkbowl.vault.permission.Permission;
@@ -14,11 +15,7 @@ import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.InventoryView;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin;
import sh.okx.rankup.commands.InfoCommand;
import sh.okx.rankup.commands.PrestigeCommand;
import sh.okx.rankup.commands.PrestigesCommand;
import sh.okx.rankup.commands.RanksCommand;
import sh.okx.rankup.commands.RankupCommand;
import sh.okx.rankup.commands.*;
import sh.okx.rankup.gui.Gui;
import sh.okx.rankup.gui.GuiListener;
import sh.okx.rankup.messages.EmptyMessageBuilder;
@@ -33,25 +30,22 @@ import sh.okx.rankup.ranks.Rankups;
import sh.okx.rankup.requirements.OperationRegistry;
import sh.okx.rankup.requirements.Requirement;
import sh.okx.rankup.requirements.RequirementRegistry;
import sh.okx.rankup.requirements.operation.AllOperation;
import sh.okx.rankup.requirements.operation.AnyOperation;
import sh.okx.rankup.requirements.operation.NoneOperation;
import sh.okx.rankup.requirements.operation.OneOperation;
import sh.okx.rankup.requirements.requirement.GroupRequirement;
import sh.okx.rankup.requirements.requirement.advancedachievements.AdvancedAchievementsAchievementRequirement;
import sh.okx.rankup.requirements.requirement.advancedachievements.AdvancedAchievementsTotalRequirement;
import sh.okx.rankup.requirements.requirement.mcmmo.McMMOPowerLevelRequirement;
import sh.okx.rankup.requirements.requirement.mcmmo.McMMOSkillRequirement;
import sh.okx.rankup.requirements.requirement.MoneyRequirement;
import sh.okx.rankup.requirements.requirement.PermissionRequirement;
import sh.okx.rankup.requirements.requirement.PlaceholderRequirement;
import sh.okx.rankup.requirements.requirement.PlaytimeMinutesRequirement;
import sh.okx.rankup.requirements.requirement.XpLevelRequirement;
import sh.okx.rankup.requirements.operation.*;
import sh.okx.rankup.requirements.requirement.*;
import sh.okx.rankup.requirements.requirement.advancedachievements.*;
import sh.okx.rankup.requirements.requirement.mcmmo.*;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.WeakHashMap;
import java.util.function.Supplier;
@@ -90,12 +84,16 @@ public class Rankup extends JavaPlugin {
reload();
Metrics metrics = new Metrics(this);
metrics.addCustomChart(new Metrics.SimplePie("confirmation") {
@Override
public String getValue() {
return getConfig().getString("confirmation.type");
metrics.addCustomChart(new Metrics.SimplePie("confirmation",
() -> config.getString("confirmation.type")));
metrics.addCustomChart(new Metrics.AdvancedPie("requirements", () -> {
Map<String, Integer> map = new HashMap<>();
addAll(map, rankups);
if (prestiges != null) {
addAll(map, prestiges);
}
});
return map;
}));
if (config.getBoolean("ranks")) {
getCommand("ranks").setExecutor(new RanksCommand(this));
@@ -136,7 +134,7 @@ public class Rankup extends JavaPlugin {
autoRankup.runTaskTimer(this, time, time);
}
if (config.getInt("version") < 2) {
if (config.getInt("version") < 3) {
getLogger().severe("You are using an outdated config!");
getLogger().severe("This means that some things might not work!");
getLogger().severe("To update, please rename ALL your config files (or the folder they are in),");
@@ -147,6 +145,15 @@ public class Rankup extends JavaPlugin {
}
}
private void addAll(Map<String, Integer> map, RankList<? extends Rank> ranks) {
for (Rank rank : ranks.ranks) {
for (Requirement requirement : rank.getRequirements()) {
String name = requirement.getName();
map.put(name, map.getOrDefault(name, 0) + 1);
}
}
}
/**
* Closes all rankup inventories on disable
* so players cannot grab items from the inventory
@@ -163,8 +170,13 @@ public class Rankup extends JavaPlugin {
}
private void loadConfigs() {
messages = loadConfig("messages.yml");
saveLocales();
config = loadConfig("config.yml");
String locale = config.getString("locale");
File localeFile = new File(new File(getDataFolder(), "locale"), locale + ".yml");
messages = YamlConfiguration.loadConfiguration(localeFile);
Bukkit.getScheduler().scheduleSyncDelayedTask(this, this::refreshRanks);
}
@@ -178,6 +190,18 @@ public class Rankup extends JavaPlugin {
}
}
private void saveLocales() {
saveLocale("en");
}
private void saveLocale(String locale) {
String name = "locale/" + locale + ".yml";
File file = new File(getDataFolder(), name);
if (!file.exists()) {
saveResource("locale/" + locale + ".yml", false);
}
}
private FileConfiguration loadConfig(String name) {
File file = new File(getDataFolder(), name);
if (!file.exists()) {
@@ -1,8 +1,5 @@
package sh.okx.rankup.messages;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public enum Variable {
PLAYER,
OLD_RANK,
@@ -18,11 +15,5 @@ public enum Variable {
PERCENT_DONE,
PERCENT_LEFT,
SECONDS,
SECONDS_LEFT;
public String replace(String message, String value, String type) {
Pattern pattern = Pattern.compile("\\{" + type + "_" + this + "}", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(message);
return matcher.replaceAll(value);
}
SECONDS_LEFT
}
@@ -14,39 +14,14 @@ public class PlaceholderRequirement extends Requirement {
super(clone);
}
private double getValue(Player player) {
String[] parts = getValueString().split(" ", 2);
String parsed = PlaceholderAPI.setPlaceholders(player, parts[0]);
if(!PlaceholderAPI.containsPlaceholders(parts[0]) || parsed.equals(parts[0])) {
plugin.getLogger().severe(parts[0] + " is not a PlaceholderAPI placeholder!");
return -1;
}
double value;
try {
value = Double.parseDouble(parsed);
} catch(NumberFormatException ex) {
plugin.getLogger().severe("Parsed placeholder '" +parsed + "' is not a valid number");
return -1;
}
return value;
}
private double getNeeded() {
String needed = getValueString().split(" ", 2)[1];
try {
return Double.parseDouble(needed);
} catch(NumberFormatException e) {
plugin.getLogger().severe("Needed '" + needed + "' is not a valid number!");
return -1;
}
}
@Override
public boolean check(Player player) {
String[] parts = getValueString().split(" ");
String parsed = PlaceholderAPI.setPlaceholders(player, parts[0]);
if(!PlaceholderAPI.containsPlaceholders(parts[0]) || parsed.equals(parts[0])) {
throw new IllegalArgumentException(parts[0] + " is not a PlaceholderAPI placeholder!");
} else if (parts.length < 3) {
throw new IllegalArgumentException("Placeholder requirements must be in the form %placeholder% <operation> string");
}
String value = parts[2];
+7 -1
View File
@@ -1,5 +1,11 @@
# this is used for letting you know that you need to update/change your config file
version: 2
version: 3
# the ISO-639-1 locale to use for messages
# all messages can be customised but this allows you to
# choose messages that are already translated
# locales can be found in the locale/ folder
locale: en
# interval (in minutes) to check to autorankup players
# ranking up manually wil always be enabled
@@ -56,8 +56,8 @@ prestige:
header: ""
footer: ""
cooldown:
singular: "&cYou must wait {SECONDS_LEFT} second to prestige again."
plural: "&cYou must wait {SECONDS_LEFT} more seconds to prestige again."
singular: "&cYou must wait {SECONDS_LEFT} second to prestige again."
plural: "&cYou must wait {SECONDS_LEFT} more seconds to prestige again."
not-high-enough: "&cYou cannot prestige at your rank!"
not-in-ladder: "&cSorry, but we could not find any rankups for the group(s) you are in."
+1 -1
View File
@@ -1,5 +1,5 @@
name: Rankup
version: 3.3.1
version: 3.3.2-beta
main: sh.okx.rankup.Rankup
author: Okx
depend: [Vault]