Taboolib 5.0 fully refactored & Not a plugin now.
This commit is contained in:
654
src/main/scala/io/izzel/taboolib/Metrics.java
Normal file
654
src/main/scala/io/izzel/taboolib/Metrics.java
Normal file
@@ -0,0 +1,654 @@
|
||||
package io.izzel.taboolib;
|
||||
|
||||
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.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.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.logging.Level;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
/**
|
||||
* bStats collects some data for plugin authors.
|
||||
* Check out https://bStats.org/ to learn more about bStats!
|
||||
*
|
||||
* @author Bastian
|
||||
*/
|
||||
public class Metrics {
|
||||
|
||||
// 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/bukkit";
|
||||
// Should failed requests be logged?
|
||||
private static boolean logFailedRequests;
|
||||
// The uuid of the server
|
||||
private static String serverUUID;
|
||||
|
||||
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 plugin
|
||||
private final Plugin plugin;
|
||||
|
||||
// A list with all custom charts
|
||||
private final List<CustomChart> charts = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param plugin The plugin which stats should be submitted.
|
||||
*/
|
||||
public Metrics(Plugin plugin) {
|
||||
if (plugin == null) {
|
||||
throw new IllegalArgumentException("Plugin cannot be null!");
|
||||
}
|
||||
this.plugin = plugin;
|
||||
|
||||
// Get the config file
|
||||
File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats");
|
||||
File configFile = new File(bStatsFolder, "config.yml");
|
||||
YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile);
|
||||
|
||||
// Check if the config file exists
|
||||
if (!config.isSet("serverUuid")) {
|
||||
// Add default values
|
||||
config.addDefault("enabled", true);
|
||||
// Every server gets it's unique random id.
|
||||
config.addDefault("serverUuid", UUID.randomUUID().toString());
|
||||
// Should failed request be logged?
|
||||
config.addDefault("logFailedRequests", false);
|
||||
try {
|
||||
config.save(configFile);
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
// Load the data
|
||||
serverUUID = config.getString("serverUuid");
|
||||
logFailedRequests = config.getBoolean("logFailedRequests", false);
|
||||
if (config.getBoolean("enabled", true)) {
|
||||
boolean found = false;
|
||||
// Search for all other bStats Metrics classes to see if we are the first one
|
||||
for (Class<?> service : Bukkit.getServicesManager().getKnownServices()) {
|
||||
try {
|
||||
service.getField("B_STATS_VERSION"); // Our identifier :)
|
||||
found = true; // We aren't the first
|
||||
break;
|
||||
} catch (NoSuchFieldException ignored) {
|
||||
}
|
||||
}
|
||||
// Register our service
|
||||
Bukkit.getServicesManager().register(Metrics.class, this, plugin, ServicePriority.Normal);
|
||||
if (!found) {
|
||||
// We are the first!
|
||||
startSubmitting();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the data to the bStats server.
|
||||
*
|
||||
* @param data The data to send.
|
||||
* @throws Exception If the request failed.
|
||||
*/
|
||||
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(StandardCharsets.UTF_8));
|
||||
gzip.close();
|
||||
return outputStream.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a custom chart.
|
||||
*
|
||||
* @param chart The chart to add.
|
||||
*/
|
||||
public void addCustomChart(CustomChart chart) {
|
||||
if (chart == null) {
|
||||
throw new IllegalArgumentException("Chart cannot be null!");
|
||||
}
|
||||
charts.add(chart);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the Scheduler which submits our data every 30 minutes.
|
||||
*/
|
||||
private void startSubmitting() {
|
||||
final Timer timer = new Timer(true); // We use a timer cause the Bukkit scheduler is affected by server lags
|
||||
timer.scheduleAtFixedRate(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!plugin.isEnabled()) { // Plugin was disabled
|
||||
timer.cancel();
|
||||
return;
|
||||
}
|
||||
// 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();
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 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
|
||||
// WARNING: Changing the frequency has no effect but your plugin WILL be blocked/deleted!
|
||||
// WARNING: Just don't do it!
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the plugin specific data.
|
||||
* This method is called using Reflection.
|
||||
*
|
||||
* @return The plugin specific data.
|
||||
*/
|
||||
public JSONObject getPluginData() {
|
||||
JSONObject data = new JSONObject();
|
||||
|
||||
String pluginName = plugin.getDescription().getName();
|
||||
String pluginVersion = plugin.getDescription().getVersion();
|
||||
|
||||
data.put("pluginName", pluginName); // Append the name of the plugin
|
||||
data.put("pluginVersion", pluginVersion); // Append the version of the plugin
|
||||
JSONArray customCharts = new JSONArray();
|
||||
for (CustomChart customChart : charts) {
|
||||
// Add the data of the custom charts
|
||||
JSONObject chart = customChart.getRequestJsonObject();
|
||||
if (chart == null) { // If the chart is null, we skip it
|
||||
continue;
|
||||
}
|
||||
customCharts.add(chart);
|
||||
}
|
||||
data.put("customCharts", customCharts);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the server specific data.
|
||||
*
|
||||
* @return The server specific data.
|
||||
*/
|
||||
private JSONObject getServerData() {
|
||||
// Minecraft specific data
|
||||
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 = Bukkit.getVersion();
|
||||
bukkitVersion = bukkitVersion.substring(bukkitVersion.indexOf("MC: ") + 4, bukkitVersion.length() - 1);
|
||||
|
||||
// OS/Java specific data
|
||||
String javaVersion = System.getProperty("java.version");
|
||||
String osName = System.getProperty("os.name");
|
||||
String osArch = System.getProperty("os.arch");
|
||||
String osVersion = System.getProperty("os.version");
|
||||
int coreCount = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
JSONObject data = new JSONObject();
|
||||
|
||||
data.put("serverUUID", serverUUID);
|
||||
|
||||
data.put("playerAmount", playerAmount);
|
||||
data.put("onlineMode", onlineMode);
|
||||
data.put("bukkitVersion", bukkitVersion);
|
||||
|
||||
data.put("javaVersion", javaVersion);
|
||||
data.put("osName", osName);
|
||||
data.put("osArch", osArch);
|
||||
data.put("osVersion", osVersion);
|
||||
data.put("coreCount", coreCount);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects the data and sends it afterwards.
|
||||
*/
|
||||
private void submitData() {
|
||||
final JSONObject data = getServerData();
|
||||
|
||||
JSONArray pluginData = new JSONArray();
|
||||
// Search for all other bStats Metrics classes to get their plugin data
|
||||
for (Class<?> service : Bukkit.getServicesManager().getKnownServices()) {
|
||||
try {
|
||||
service.getField("B_STATS_VERSION"); // Our identifier :)
|
||||
|
||||
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);
|
||||
|
||||
// Create a new thread for the connection to the bStats server
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
// Send the data
|
||||
sendData(data);
|
||||
} catch (Exception e) {
|
||||
// Something went wrong! :(
|
||||
if (logFailedRequests) {
|
||||
plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats of " + plugin.getName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a custom chart.
|
||||
*/
|
||||
public static abstract class CustomChart {
|
||||
|
||||
// The id of the chart
|
||||
final String chartId;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param chartId The id of the chart.
|
||||
*/
|
||||
CustomChart(String chartId) {
|
||||
if (chartId == null || chartId.isEmpty()) {
|
||||
throw new IllegalArgumentException("ChartId cannot be null or empty!");
|
||||
}
|
||||
this.chartId = chartId;
|
||||
}
|
||||
|
||||
private JSONObject getRequestJsonObject() {
|
||||
JSONObject chart = new JSONObject();
|
||||
chart.put("chartId", chartId);
|
||||
try {
|
||||
JSONObject data = getChartData();
|
||||
if (data == null) {
|
||||
// If the data is null we don't send the chart.
|
||||
return null;
|
||||
}
|
||||
chart.put("data", data);
|
||||
} catch (Throwable t) {
|
||||
if (logFailedRequests) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "Failed to get data for custom chart with id " + chartId, t);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return chart;
|
||||
}
|
||||
|
||||
protected abstract JSONObject getChartData() throws Exception;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a custom simple pie.
|
||||
*/
|
||||
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, Callable<String> callable) {
|
||||
super(chartId);
|
||||
this.callable = callable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JSONObject getChartData() throws Exception {
|
||||
JSONObject data = new JSONObject();
|
||||
String value = callable.call();
|
||||
if (value == null || value.isEmpty()) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
data.put("value", value);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a custom advanced pie.
|
||||
*/
|
||||
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, Callable<Map<String, Integer>> callable) {
|
||||
super(chartId);
|
||||
this.callable = callable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JSONObject getChartData() throws Exception {
|
||||
JSONObject data = new JSONObject();
|
||||
JSONObject values = new JSONObject();
|
||||
Map<String, Integer> map = callable.call();
|
||||
if (map == null || map.isEmpty()) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
boolean allSkipped = true;
|
||||
for (Map.Entry<String, Integer> entry : map.entrySet()) {
|
||||
if (entry.getValue() == 0) {
|
||||
continue; // Skip this invalid
|
||||
}
|
||||
allSkipped = false;
|
||||
values.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
if (allSkipped) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
data.put("values", values);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a custom drilldown pie.
|
||||
*/
|
||||
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 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;
|
||||
|
||||
/**
|
||||
* 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, Callable<Integer> callable) {
|
||||
super(chartId);
|
||||
this.callable = callable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JSONObject getChartData() throws Exception {
|
||||
JSONObject data = new JSONObject();
|
||||
int value = callable.call();
|
||||
if (value == 0) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
data.put("value", value);
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a custom multi line chart.
|
||||
*/
|
||||
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, Callable<Map<String, Integer>> callable) {
|
||||
super(chartId);
|
||||
this.callable = callable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JSONObject getChartData() throws Exception {
|
||||
JSONObject data = new JSONObject();
|
||||
JSONObject values = new JSONObject();
|
||||
Map<String, Integer> map = callable.call();
|
||||
if (map == null || map.isEmpty()) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
boolean allSkipped = true;
|
||||
for (Map.Entry<String, Integer> entry : map.entrySet()) {
|
||||
if (entry.getValue() == 0) {
|
||||
continue; // Skip this invalid
|
||||
}
|
||||
allSkipped = false;
|
||||
values.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
if (allSkipped) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
data.put("values", values);
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a custom simple bar chart.
|
||||
*/
|
||||
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 SimpleBarChart(String chartId, Callable<Map<String, Integer>> callable) {
|
||||
super(chartId);
|
||||
this.callable = callable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JSONObject getChartData() throws Exception {
|
||||
JSONObject data = new JSONObject();
|
||||
JSONObject values = new JSONObject();
|
||||
Map<String, Integer> map = callable.call();
|
||||
if (map == null || map.isEmpty()) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
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 bar chart.
|
||||
*/
|
||||
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 AdvancedBarChart(String chartId, Callable<Map<String, int[]>> callable) {
|
||||
super(chartId);
|
||||
this.callable = callable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JSONObject getChartData() throws Exception {
|
||||
JSONObject data = new JSONObject();
|
||||
JSONObject values = new JSONObject();
|
||||
Map<String, int[]> map = callable.call();
|
||||
if (map == null || map.isEmpty()) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
boolean allSkipped = true;
|
||||
for (Map.Entry<String, int[]> entry : map.entrySet()) {
|
||||
if (entry.getValue().length == 0) {
|
||||
continue; // Skip this invalid
|
||||
}
|
||||
allSkipped = false;
|
||||
JSONArray categoryValues = new JSONArray();
|
||||
for (int categoryValue : entry.getValue()) {
|
||||
categoryValues.add(categoryValue);
|
||||
}
|
||||
values.put(entry.getKey(), categoryValues);
|
||||
}
|
||||
if (allSkipped) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
data.put("values", values);
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
109
src/main/scala/io/izzel/taboolib/PluginLoader.java
Normal file
109
src/main/scala/io/izzel/taboolib/PluginLoader.java
Normal file
@@ -0,0 +1,109 @@
|
||||
package io.izzel.taboolib;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import io.izzel.taboolib.locale.TLocaleLoader;
|
||||
import io.izzel.taboolib.module.command.TCommandHandler;
|
||||
import io.izzel.taboolib.module.config.TConfig;
|
||||
import io.izzel.taboolib.module.config.TConfigWatcher;
|
||||
import io.izzel.taboolib.module.dependency.TDependencyInjector;
|
||||
import io.izzel.taboolib.module.inject.TListenerHandler;
|
||||
import io.izzel.taboolib.module.mysql.IHost;
|
||||
import io.izzel.taboolib.module.mysql.hikari.HikariHandler;
|
||||
import io.izzel.taboolib.origin.database.PluginDataManager;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @Author 坏黑
|
||||
* @Since 2019-07-05 15:14
|
||||
*/
|
||||
public abstract class PluginLoader {
|
||||
|
||||
private static List<PluginLoader> registerLoader = Lists.newArrayList();
|
||||
private static Set<String> plugins = Sets.newHashSet();
|
||||
|
||||
static {
|
||||
registerLoader.add(new PluginLoader() {
|
||||
|
||||
@Override
|
||||
public void onLoading(Plugin plugin) {
|
||||
// 加载语言文件
|
||||
TLocaleLoader.load(plugin, false);
|
||||
// 注入依赖
|
||||
TDependencyInjector.inject(plugin, plugin.getClass());
|
||||
// 读取插件类
|
||||
TabooLibLoader.setupClasses(plugin);
|
||||
// 加载插件类
|
||||
TabooLibLoader.getPluginClassSafely(plugin).forEach(c -> TabooLibLoader.preLoadClass(plugin, c));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStarting(Plugin plugin) {
|
||||
// 加载监听器
|
||||
TListenerHandler.setupListener(plugin);
|
||||
// 加载插件类
|
||||
TabooLibLoader.getPluginClassSafely(plugin).forEach(c -> TabooLibLoader.postLoadClass(plugin, c));
|
||||
// 注册插件命令
|
||||
TCommandHandler.registerCommand(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivated(Plugin plugin) {
|
||||
// 注册监听器
|
||||
TListenerHandler.registerListener(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopping(Plugin plugin) {
|
||||
// 注销监听器
|
||||
TListenerHandler.cancelListener(plugin);
|
||||
// 储存插件数据
|
||||
PluginDataManager.saveAllCaches(plugin, true);
|
||||
// 注销数据库连接
|
||||
Sets.newHashSet(HikariHandler.getDataSource().keySet()).stream().filter(IHost::isAutoClose).forEach(HikariHandler::closeDataSource);
|
||||
// 释放文检动态读取
|
||||
Optional.ofNullable(TConfig.getFiles().remove(plugin.getName())).ifPresent(files -> files.forEach(file -> TConfigWatcher.getInst().removeListener(file)));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void onLoading(Plugin plugin) {
|
||||
}
|
||||
|
||||
public void onStarting(Plugin plugin) {
|
||||
}
|
||||
|
||||
public void onActivated(Plugin plugin) {
|
||||
}
|
||||
|
||||
public void onStopping(Plugin plugin) {
|
||||
}
|
||||
|
||||
public static void addPlugin(Plugin plugin) {
|
||||
plugins.add(plugin.getName());
|
||||
}
|
||||
|
||||
public static void load(Plugin plugin) {
|
||||
registerLoader.forEach(loader -> loader.onLoading(plugin));
|
||||
}
|
||||
|
||||
public static void start(Plugin plugin) {
|
||||
registerLoader.forEach(loader -> loader.onStarting(plugin));
|
||||
}
|
||||
|
||||
public static void active(Plugin plugin) {
|
||||
registerLoader.forEach(loader -> loader.onActivated(plugin));
|
||||
}
|
||||
|
||||
public static void stop(Plugin plugin) {
|
||||
registerLoader.forEach(loader -> loader.onStopping(plugin));
|
||||
}
|
||||
|
||||
public static boolean isPlugin(Plugin plugin) {
|
||||
return plugins.contains(plugin.getName());
|
||||
}
|
||||
}
|
||||
137
src/main/scala/io/izzel/taboolib/TabooLib.java
Normal file
137
src/main/scala/io/izzel/taboolib/TabooLib.java
Normal file
@@ -0,0 +1,137 @@
|
||||
package io.izzel.taboolib;
|
||||
|
||||
import io.izzel.taboolib.locale.TLocaleLoader;
|
||||
import io.izzel.taboolib.module.config.TConfig;
|
||||
import io.izzel.taboolib.module.config.TConfigWatcher;
|
||||
import io.izzel.taboolib.module.dependency.Dependency;
|
||||
import io.izzel.taboolib.module.logger.TLogger;
|
||||
import io.izzel.taboolib.module.mysql.hikari.HikariHandler;
|
||||
import io.izzel.taboolib.module.nms.NMSHandler;
|
||||
import io.izzel.taboolib.origin.database.PlayerDataManager;
|
||||
import io.izzel.taboolib.origin.database.PluginDataManager;
|
||||
import io.izzel.taboolib.plugin.InternalPlugin;
|
||||
import io.izzel.taboolib.util.Files;
|
||||
import io.izzel.taboolib.util.IO;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.util.NumberConversions;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* @Author 坏黑
|
||||
* @Since 2019-07-05 10:39
|
||||
* <p>
|
||||
* 注意与 TabooLib4.x 版本的兼容
|
||||
* 可能存在同时运行的情况
|
||||
*/
|
||||
@Dependency(type = Dependency.Type.LIBRARY, maven = "org.slf4j:slf4j-api:1.7.25", url = "https://skymc.oss-cn-shanghai.aliyuncs.com/libs/org.slf4j-slf4j-api-1.7.25.jar")
|
||||
@Dependency(type = Dependency.Type.LIBRARY, maven = "com.zaxxer:HikariCP:3.1.0", url = "https://skymc.oss-cn-shanghai.aliyuncs.com/libs/com.zaxxer-HikariCP-3.1.0.jar")
|
||||
@Dependency(type = Dependency.Type.LIBRARY, maven = "org.scala-lang:scala-library:2.12.8", url = "https://skymc.oss-cn-shanghai.aliyuncs.com/libs/scala-library-2.12.8.jar")
|
||||
public class TabooLib {
|
||||
|
||||
private static TabooLib inst = new TabooLib();
|
||||
private static TLogger logger;
|
||||
private static TConfig config;
|
||||
private static double version;
|
||||
|
||||
// 第三方依赖下载位置
|
||||
private File libsFolder;
|
||||
private File playerDataFolder;
|
||||
private File serverDataFolder;
|
||||
|
||||
// 内部语言文件
|
||||
private YamlConfiguration internal = new YamlConfiguration();
|
||||
|
||||
public TabooLib() {
|
||||
// 创建配置
|
||||
inst = this;
|
||||
logger = TLogger.getUnformatted("TabooLib");
|
||||
config = TConfig.create(getPlugin(), "config.yml");
|
||||
libsFolder = Files.folder("plugins/TabooLib/libs");
|
||||
playerDataFolder = Files.folder(config.getString("DATAURL.PLAYER-DATA"));
|
||||
serverDataFolder = Files.folder(config.getString("DATAURL.SERVER-DATA"));
|
||||
// 加载版本号
|
||||
try {
|
||||
version = NumberConversions.toDouble(IO.readFully(Files.getResource("version"), Charset.forName("utf-8")));
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
// 加载内部语言文件
|
||||
try {
|
||||
internal.loadFromString(IO.readFully(Files.getResource("lang/internal.yml"), Charset.forName("utf-8")));
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
// 加载 TabooLib 语言文件
|
||||
TLocaleLoader.load(getPlugin(), false);
|
||||
// 加载 TabooLib
|
||||
TabooLibLoader.init();
|
||||
// 创建 TabooLib 插件数据
|
||||
PluginDataManager.addPluginData("TabooLib", null);
|
||||
PluginDataManager.addPluginData("TabooLibrary", null);
|
||||
// 创建线程检测服务器是否关闭
|
||||
Executors.newSingleThreadExecutor().submit(() -> {
|
||||
while (NMSHandler.getHandler().isRunning()) {
|
||||
}
|
||||
// 关闭连接池
|
||||
HikariHandler.closeDataSourceForce();
|
||||
// 保存数据
|
||||
PlayerDataManager.saveAllPlayers(false, true);
|
||||
PluginDataManager.saveAllCaches();
|
||||
// 插件关闭
|
||||
PluginLoader.stop(getPlugin());
|
||||
// 清理数据
|
||||
if (config.getBoolean("DELETE-DATA")) {
|
||||
Files.deepDelete(getPlayerDataFolder());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
TConfigWatcher.getInst().unregisterAll();
|
||||
}
|
||||
|
||||
public static InternalPlugin getPlugin() {
|
||||
return InternalPlugin.getPlugin();
|
||||
}
|
||||
|
||||
// *********************************
|
||||
//
|
||||
// Getter and Setter
|
||||
//
|
||||
// *********************************
|
||||
|
||||
public static TabooLib getInst() {
|
||||
return inst;
|
||||
}
|
||||
|
||||
public static TLogger getLogger() {
|
||||
return logger;
|
||||
}
|
||||
|
||||
public static TConfig getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public static double getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public File getLibsFolder() {
|
||||
return libsFolder;
|
||||
}
|
||||
|
||||
public File getPlayerDataFolder() {
|
||||
return playerDataFolder;
|
||||
}
|
||||
|
||||
public File getServerDataFolder() {
|
||||
return serverDataFolder;
|
||||
}
|
||||
|
||||
public YamlConfiguration getInternal() {
|
||||
return internal;
|
||||
}
|
||||
}
|
||||
91
src/main/scala/io/izzel/taboolib/TabooLibAPI.java
Normal file
91
src/main/scala/io/izzel/taboolib/TabooLibAPI.java
Normal file
@@ -0,0 +1,91 @@
|
||||
package io.izzel.taboolib;
|
||||
|
||||
import io.izzel.taboolib.module.nms.NMSHandler;
|
||||
import io.izzel.taboolib.origin.database.PluginDataManager;
|
||||
import io.izzel.taboolib.util.Strings;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
import org.bukkit.event.server.ServerCommandEvent;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* @Author 坏黑
|
||||
* @Since 2019-07-05 14:31
|
||||
*/
|
||||
public class TabooLibAPI {
|
||||
|
||||
private static boolean bukkit;
|
||||
private static boolean originLoaded;
|
||||
|
||||
static {
|
||||
try {
|
||||
// 判断是否基于 Bukkit 运行
|
||||
bukkit = Class.forName("org.bukkit.Bukkit") != null;
|
||||
// 获取 TabooLib4.x 版本是否载入
|
||||
originLoaded = Bukkit.getPluginManager().getPlugin("TabooLib") != null;
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isBukkit() {
|
||||
return bukkit;
|
||||
}
|
||||
|
||||
public static boolean isOriginLoaded() {
|
||||
return originLoaded;
|
||||
}
|
||||
|
||||
public static boolean isDependTabooLib(Plugin plugin) {
|
||||
return PluginLoader.isPlugin(plugin);
|
||||
}
|
||||
|
||||
public static double[] getTPS() {
|
||||
return NMSHandler.getHandler().getTPS();
|
||||
}
|
||||
|
||||
public static boolean isDebug() {
|
||||
return PluginDataManager.getPluginData("TabooLibrary", TabooLib.getPlugin()).getBoolean("debug");
|
||||
}
|
||||
|
||||
public static void setDebug(boolean debug) {
|
||||
PluginDataManager.getPluginData("TabooLibrary", TabooLib.getPlugin()).set("debug", debug);
|
||||
}
|
||||
|
||||
public static void debug(String... args) {
|
||||
debug(TabooLib.getPlugin(), args);
|
||||
}
|
||||
|
||||
public static void debug(Plugin plugin, String... args) {
|
||||
if (!isDebug()) {
|
||||
return;
|
||||
}
|
||||
for (String line : args) {
|
||||
Bukkit.getConsoleSender().sendMessage("§4[" + plugin.getName() + "][DEBUG] §c" + line);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean dispatchCommand(CommandSender sender, String command) {
|
||||
try {
|
||||
if ((sender instanceof Player)) {
|
||||
PlayerCommandPreprocessEvent e = new PlayerCommandPreprocessEvent((Player) sender, "/" + command);
|
||||
Bukkit.getPluginManager().callEvent(e);
|
||||
if (e.isCancelled() || Strings.isBlank(e.getMessage()) || !e.getMessage().startsWith("/")) {
|
||||
return false;
|
||||
}
|
||||
return Bukkit.dispatchCommand(e.getPlayer(), e.getMessage().substring(1));
|
||||
} else {
|
||||
ServerCommandEvent e = new ServerCommandEvent(sender, command);
|
||||
Bukkit.getPluginManager().callEvent(e);
|
||||
if (e.isCancelled() || Strings.isBlank(e.getCommand())) {
|
||||
return false;
|
||||
}
|
||||
return Bukkit.dispatchCommand(e.getSender(), e.getCommand());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
159
src/main/scala/io/izzel/taboolib/TabooLibLoader.java
Normal file
159
src/main/scala/io/izzel/taboolib/TabooLibLoader.java
Normal file
@@ -0,0 +1,159 @@
|
||||
package io.izzel.taboolib;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import io.izzel.taboolib.module.dependency.TDependencyInjector;
|
||||
import io.izzel.taboolib.module.inject.TSchedule;
|
||||
import io.izzel.taboolib.origin.client.TabooLibClient;
|
||||
import io.izzel.taboolib.origin.client.TabooLibServer;
|
||||
import io.izzel.taboolib.origin.database.PlayerDataManager;
|
||||
import io.izzel.taboolib.origin.database.PluginDataManager;
|
||||
import io.izzel.taboolib.util.Files;
|
||||
import io.izzel.taboolib.util.Reflection;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @Author 坏黑
|
||||
* @Since 2019-07-05 15:30
|
||||
*/
|
||||
public class TabooLibLoader {
|
||||
|
||||
static Map<String, List<Class>> pluginClasses = Maps.newHashMap();
|
||||
static List<Loader> loaders = Lists.newArrayList();
|
||||
|
||||
@TSchedule(period = 20 * 60, async = true)
|
||||
static void save() {
|
||||
PluginDataManager.saveAllCaches();
|
||||
PlayerDataManager.saveAllCaches(true, false);
|
||||
}
|
||||
|
||||
@TSchedule
|
||||
static void start() {
|
||||
PluginLoader.active(TabooLib.getPlugin());
|
||||
// 通讯网络服务器
|
||||
if (TabooLib.getConfig().getBoolean("SERVER")) {
|
||||
TabooLibServer.main(new String[0]);
|
||||
}
|
||||
// 通讯网络客户端
|
||||
TabooLibClient.init();
|
||||
}
|
||||
|
||||
static void init() {
|
||||
// 加载依赖
|
||||
TDependencyInjector.inject("TabooLib", TabooLib.class);
|
||||
// 插件统计
|
||||
Metrics metrics = new Metrics(TabooLib.getPlugin());
|
||||
metrics.addCustomChart(new Metrics.SingleLineChart("plugins_using_taboolib", () -> Math.toIntExact(Arrays.stream(Bukkit.getPluginManager().getPlugins()).filter(TabooLibAPI::isDependTabooLib).count())));
|
||||
// 读取插件类
|
||||
setupClasses(TabooLib.getPlugin());
|
||||
// 读取加载器
|
||||
pluginClasses.get("TabooLib").stream().filter(TabooLibLoader::isLoader).forEach(pluginClass -> {
|
||||
try {
|
||||
loaders.add((Loader) Reflection.instantiateObject(pluginClass));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
loaders.sort(Comparator.comparingInt(Loader::priority));
|
||||
});
|
||||
// 加载插件
|
||||
PluginLoader.load(TabooLib.getPlugin());
|
||||
PluginLoader.start(TabooLib.getPlugin());
|
||||
}
|
||||
|
||||
public static Optional<List<Class>> getPluginClasses(Plugin plugin) {
|
||||
return Optional.ofNullable(pluginClasses.get(plugin.getName()));
|
||||
}
|
||||
|
||||
public static List<Class> getPluginClassSafely(Plugin plugin) {
|
||||
List<Class> classes = pluginClasses.get(plugin.getName());
|
||||
return classes == null ? new ArrayList<>() : new ArrayList<>(classes);
|
||||
}
|
||||
|
||||
static boolean isLoader(Class pluginClass) {
|
||||
return !Loader.class.equals(pluginClass) && Loader.class.isAssignableFrom(pluginClass);
|
||||
}
|
||||
|
||||
static void setupClasses(Plugin plugin) {
|
||||
try {
|
||||
long time = System.currentTimeMillis();
|
||||
List<Class> classes;
|
||||
IgnoreClasses annotation = plugin.getClass().getAnnotation(IgnoreClasses.class);
|
||||
if (annotation != null) {
|
||||
classes = Files.getClasses(plugin, annotation.value());
|
||||
} else {
|
||||
classes = Files.getClasses(plugin);
|
||||
}
|
||||
if (plugin.getName().equals("TabooLib")) {
|
||||
classes = classes.stream().filter(c -> c.getName().startsWith("io.izzel")).collect(Collectors.toList());
|
||||
}
|
||||
TabooLibAPI.debug("Saved " + classes.size() + " classes (" + plugin.getName() + ") (" + (System.currentTimeMillis() - time) + "ms)");
|
||||
pluginClasses.put(plugin.getName(), classes);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
static void preLoadClass(Plugin plugin, Class<?> loadClass) {
|
||||
loaders.forEach(loader -> {
|
||||
try {
|
||||
loader.preLoad(plugin, loadClass);
|
||||
} catch (NoClassDefFoundError ignore) {
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void postLoadClass(Plugin plugin, Class<?> loadClass) {
|
||||
loaders.forEach(loader -> {
|
||||
try {
|
||||
loader.postLoad(plugin, loadClass);
|
||||
} catch (NoClassDefFoundError ignore) {
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void unloadClass(Plugin plugin, Class<?> loadClass) {
|
||||
loaders.forEach(loader -> {
|
||||
try {
|
||||
loader.unload(plugin, loadClass);
|
||||
} catch (NoClassDefFoundError ignore) {
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public interface Loader {
|
||||
|
||||
default void preLoad(org.bukkit.plugin.Plugin plugin, Class<?> loadClass) {
|
||||
}
|
||||
|
||||
default void postLoad(org.bukkit.plugin.Plugin plugin, Class<?> loadClass) {
|
||||
}
|
||||
|
||||
default void unload(Plugin plugin, Class<?> cancelClass) {
|
||||
}
|
||||
|
||||
default int priority() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface IgnoreClasses {
|
||||
|
||||
String[] value();
|
||||
|
||||
}
|
||||
}
|
||||
57
src/main/scala/io/izzel/taboolib/Version.java
Normal file
57
src/main/scala/io/izzel/taboolib/Version.java
Normal file
@@ -0,0 +1,57 @@
|
||||
package io.izzel.taboolib;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
/**
|
||||
* @Author 坏黑
|
||||
* @Since 2019-07-05 14:42
|
||||
*/
|
||||
public enum Version {
|
||||
|
||||
v1_7(10700), v1_8(10800), v1_9(10900), v1_10(11000), v1_11(11100), v1_12(11200), v1_13(11300), v1_14(11400), vNull(0);
|
||||
|
||||
private int versionInt;
|
||||
|
||||
Version(int versionInt) {
|
||||
this.versionInt = versionInt;
|
||||
}
|
||||
|
||||
public int getVersionInt() {
|
||||
return versionInt;
|
||||
}
|
||||
|
||||
public static boolean isAfter(Version in) {
|
||||
return getCurrentVersion().getVersionInt() >= in.getVersionInt();
|
||||
}
|
||||
|
||||
public static boolean isBefore(Version in) {
|
||||
return getCurrentVersion().getVersionInt() < in.getVersionInt();
|
||||
}
|
||||
|
||||
public static String getBukkitVersion() {
|
||||
return Bukkit.getServer().getClass().getName().split("\\.")[3];
|
||||
}
|
||||
|
||||
public static Version getCurrentVersion() {
|
||||
String nmsVersion = getBukkitVersion();
|
||||
if (nmsVersion.startsWith("v1_7")) {
|
||||
return v1_7;
|
||||
} else if (nmsVersion.startsWith("v1_8")) {
|
||||
return v1_8;
|
||||
} else if (nmsVersion.startsWith("v1_9")) {
|
||||
return v1_9;
|
||||
} else if (nmsVersion.startsWith("v1_10")) {
|
||||
return v1_10;
|
||||
} else if (nmsVersion.startsWith("v1_11")) {
|
||||
return v1_11;
|
||||
} else if (nmsVersion.startsWith("v1_12")) {
|
||||
return v1_12;
|
||||
} else if (nmsVersion.startsWith("v1_13")) {
|
||||
return v1_13;
|
||||
} else if (nmsVersion.startsWith("v1_14")) {
|
||||
return v1_14;
|
||||
} else {
|
||||
return vNull;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
package io.izzel.taboolib.command;
|
||||
|
||||
import io.izzel.taboolib.TabooLibAPI;
|
||||
import io.izzel.taboolib.locale.TLocale;
|
||||
import io.izzel.taboolib.module.command.base.BaseMainCommand;
|
||||
import io.izzel.taboolib.module.command.base.BaseSubCommand;
|
||||
import io.izzel.taboolib.module.command.TCommand;
|
||||
import io.izzel.taboolib.module.command.base.CommandArgument;
|
||||
import io.izzel.taboolib.module.command.base.CommandRegister;
|
||||
import io.izzel.taboolib.util.ArrayUtil;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-07-04 21:32
|
||||
*/
|
||||
@TCommand(
|
||||
name = "taboolibexecute",
|
||||
aliases = {"texecute"},
|
||||
permission = "taboolib.admin"
|
||||
)
|
||||
public class TabooLibExecuteCommand extends BaseMainCommand {
|
||||
|
||||
@Override
|
||||
public String getCommandTitle() {
|
||||
return TLocale.asString("COMMANDS.TEXECUTE.COMMAND-TITLE");
|
||||
}
|
||||
|
||||
@CommandRegister(priority = 1)
|
||||
BaseSubCommand chat = new BaseSubCommand() {
|
||||
|
||||
@Override
|
||||
public String getLabel() {
|
||||
return "chat";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return TLocale.asString("COMMANDS.TEXECUTE.CHAT.DESCRIPTION");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandArgument[] getArguments() {
|
||||
return new CommandArgument[] {
|
||||
new CommandArgument(TLocale.asString("COMMANDS.TEXECUTE.CHAT.ARGUMENTS.0")),
|
||||
new CommandArgument(TLocale.asString("COMMANDS.TEXECUTE.CHAT.ARGUMENTS.1"))
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
Player player = Bukkit.getPlayerExact(args[0]);
|
||||
if (player == null) {
|
||||
TLocale.sendTo(sender, "INVALID-PLAYER-OFFLINE", args[0]);
|
||||
return;
|
||||
}
|
||||
player.chat(ArrayUtil.arrayJoin(args, 1));
|
||||
}
|
||||
};
|
||||
|
||||
@CommandRegister(priority = 1)
|
||||
BaseSubCommand command = new BaseSubCommand() {
|
||||
@Override
|
||||
public String getLabel() {
|
||||
return "command";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAliases() {
|
||||
return new String[] {"cmd"};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return TLocale.asString("COMMANDS.TEXECUTE.COMMAND.DESCRIPTION");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandArgument[] getArguments() {
|
||||
return new CommandArgument[] {
|
||||
new CommandArgument(TLocale.asString("COMMANDS.TEXECUTE.COMMAND.ARGUMENTS.0")),
|
||||
new CommandArgument(TLocale.asString("COMMANDS.TEXECUTE.COMMAND.ARGUMENTS.1"))
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (args[0].equalsIgnoreCase("console")) {
|
||||
TabooLibAPI.dispatchCommand(Bukkit.getConsoleSender(), ArrayUtil.arrayJoin(args, 1));
|
||||
return;
|
||||
}
|
||||
Player player = Bukkit.getPlayerExact(args[0]);
|
||||
if (player == null) {
|
||||
TLocale.sendTo(sender, "INVALID-TARGET-NOT-FOUND", args[0]);
|
||||
return;
|
||||
}
|
||||
TabooLibAPI.dispatchCommand(player, ArrayUtil.arrayJoin(args, 1));
|
||||
}
|
||||
};
|
||||
|
||||
@CommandRegister(priority = 2)
|
||||
BaseSubCommand commandAsOp = new BaseSubCommand() {
|
||||
|
||||
@Override
|
||||
public String getLabel() {
|
||||
return "commandAsOp";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAliases() {
|
||||
return new String[] {"op"};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return TLocale.asString("COMMANDS.TEXECUTE.COMMAND-AS-OP.DESCRIPTION");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandArgument[] getArguments() {
|
||||
return new CommandArgument[] {
|
||||
new CommandArgument(TLocale.asString("COMMANDS.TEXECUTE.COMMAND-AS-OP.ARGUMENTS.0")),
|
||||
new CommandArgument(TLocale.asString("COMMANDS.TEXECUTE.COMMAND-AS-OP.ARGUMENTS.1"))
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (args[0].equalsIgnoreCase("console")) {
|
||||
TabooLibAPI.dispatchCommand(Bukkit.getConsoleSender(), ArrayUtil.arrayJoin(args, 1));
|
||||
return;
|
||||
}
|
||||
Player player = Bukkit.getPlayerExact(args[0]);
|
||||
if (player == null) {
|
||||
TLocale.sendTo(sender, "INVALID-TARGET-NOT-FOUND", args[0]);
|
||||
return;
|
||||
}
|
||||
boolean isOp = player.isOp();
|
||||
player.setOp(true);
|
||||
try {
|
||||
TabooLibAPI.dispatchCommand(player, ArrayUtil.arrayJoin(args, 1));
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
player.setOp(isOp);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package io.izzel.taboolib.command;
|
||||
|
||||
import io.izzel.taboolib.locale.TLocale;
|
||||
import io.izzel.taboolib.locale.TLocaleLoader;
|
||||
import io.izzel.taboolib.module.command.base.BaseMainCommand;
|
||||
import io.izzel.taboolib.module.command.base.BaseSubCommand;
|
||||
import io.izzel.taboolib.module.command.TCommand;
|
||||
import io.izzel.taboolib.module.command.base.CommandArgument;
|
||||
import io.izzel.taboolib.module.command.base.CommandRegister;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
/**
|
||||
* @author sky
|
||||
* @since 2018-04-22 14:36:28
|
||||
*/
|
||||
@TCommand(
|
||||
name = "tabooliblocale",
|
||||
aliases = {"taboolocale", "tlocale"},
|
||||
permission = "taboolib.admin"
|
||||
)
|
||||
public class TabooLibLocaleCommand extends BaseMainCommand {
|
||||
|
||||
@Override
|
||||
public String getCommandTitle() {
|
||||
return TLocale.asString("COMMANDS.TLOCALE.COMMAND-TITLE");
|
||||
}
|
||||
|
||||
@CommandRegister
|
||||
BaseSubCommand send = new BaseSubCommand() {
|
||||
|
||||
@Override
|
||||
public String getLabel() {
|
||||
return "send";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return TLocale.asString("COMMANDS.TLOCALE.SEND.DESCRIPTION");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandArgument[] getArguments() {
|
||||
return new CommandArgument[] {
|
||||
new CommandArgument(TLocale.asString("COMMANDS.TLOCALE.SEND.ARGUMENTS.0")),
|
||||
new CommandArgument(TLocale.asString("COMMANDS.TLOCALE.SEND.ARGUMENTS.1")),
|
||||
new CommandArgument(TLocale.asString("COMMANDS.TLOCALE.SEND.ARGUMENTS.2"), false)
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
long time = System.currentTimeMillis();
|
||||
|
||||
List<CommandSender> target = new ArrayList<>();
|
||||
if (args[0].equalsIgnoreCase("all")) {
|
||||
target.add(Bukkit.getConsoleSender());
|
||||
target.addAll(Bukkit.getOnlinePlayers());
|
||||
} else if (args[0].equalsIgnoreCase("players")) {
|
||||
target.addAll(Bukkit.getOnlinePlayers());
|
||||
} else if (args[0].equalsIgnoreCase("console")) {
|
||||
target.add(Bukkit.getConsoleSender());
|
||||
} else {
|
||||
Player player = Bukkit.getPlayerExact(args[0]);
|
||||
if (player == null) {
|
||||
TLocale.sendTo(sender, "COMMANDS.TLOCALE.SEND.INVALID-PLAYER", args[0]);
|
||||
return;
|
||||
}
|
||||
target.add(player);
|
||||
}
|
||||
|
||||
String[] arguments;
|
||||
if (args.length > 2) {
|
||||
arguments = new String[args.length - 2];
|
||||
IntStream.range(2, args.length).forEach(i -> arguments[i - 2] = args[i]);
|
||||
} else {
|
||||
arguments = new String[0];
|
||||
}
|
||||
|
||||
/*
|
||||
* 使用命令发送其他插件文本
|
||||
* /tlocale send BlackSKY testPlugin:message
|
||||
*/
|
||||
if (args[1].contains(":")) {
|
||||
String[] path = args[1].split(":");
|
||||
Plugin plugin = Bukkit.getPluginManager().getPlugin(path[0]);
|
||||
if (plugin == null || !TLocaleLoader.isLocaleLoaded(plugin)) {
|
||||
TLocale.sendTo(sender, "COMMANDS.TLOCALE.SEND.INVALID-PLUGIN", path[0]);
|
||||
return;
|
||||
}
|
||||
if (path.length == 1) {
|
||||
TLocale.sendTo(sender, "COMMANDS.TLOCALE.SEND.INVALID-PATH", args[1]);
|
||||
return;
|
||||
}
|
||||
target.forEach(x -> TLocaleLoader.sendTo(plugin, path[1], x, arguments));
|
||||
} else {
|
||||
target.forEach(x -> TLocale.sendTo(x, args[1], arguments));
|
||||
}
|
||||
|
||||
if (sender instanceof Player && ((Player) sender).getItemInHand().getType().name().contains("COMMAND")) {
|
||||
TLocale.sendTo(sender, "COMMANDS.TLOCALE.SEND.SUCCESS-SEND", String.valueOf(System.currentTimeMillis() - time));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
package io.izzel.taboolib.command;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import io.izzel.taboolib.TabooLibAPI;
|
||||
import io.izzel.taboolib.locale.TLocale;
|
||||
import io.izzel.taboolib.module.command.TCommand;
|
||||
import io.izzel.taboolib.module.command.base.BaseMainCommand;
|
||||
import io.izzel.taboolib.module.command.base.BaseSubCommand;
|
||||
import io.izzel.taboolib.module.command.base.CommandArgument;
|
||||
import io.izzel.taboolib.module.command.base.CommandRegister;
|
||||
import io.izzel.taboolib.origin.plugin.PluginLoadState;
|
||||
import io.izzel.taboolib.origin.plugin.PluginLoadStateType;
|
||||
import io.izzel.taboolib.origin.plugin.PluginUnloadState;
|
||||
import io.izzel.taboolib.origin.plugin.PluginUtils;
|
||||
import io.izzel.taboolib.util.ArrayUtil;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-05-07 20:14
|
||||
*/
|
||||
@TCommand(
|
||||
name = "taboolibplugin",
|
||||
aliases = {"tabooplugin", "tplugin"},
|
||||
permission = "taboolib.admin"
|
||||
)
|
||||
public class TabooLibPluginCommand extends BaseMainCommand {
|
||||
|
||||
@Override
|
||||
public String getCommandTitle() {
|
||||
return TLocale.asString("COMMANDS.TPLUGIN.COMMAND-TITLE");
|
||||
}
|
||||
|
||||
@CommandRegister(priority = 1)
|
||||
BaseSubCommand load = new BaseSubCommand() {
|
||||
|
||||
@Override
|
||||
public String getLabel() {
|
||||
return "load";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return TLocale.asString("COMMANDS.TPLUGIN.LOAD.DESCRIPTION");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandArgument[] getArguments() {
|
||||
return new CommandArgument[] {new CommandArgument(TLocale.asString("COMMANDS.TPLUGIN.LOAD.ARGUMENTS.0"), true)};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
String name = ArrayUtil.arrayJoin(args, 0);
|
||||
if (PluginUtils.getPluginByName(name) != null) {
|
||||
TLocale.sendTo(sender, "COMMANDS.TPLUGIN.LOAD.INVALID-PLUGIN", name, name + " already loaded!");
|
||||
} else {
|
||||
PluginLoadState loadState;
|
||||
try {
|
||||
loadState = PluginUtils.load(name);
|
||||
} catch (Exception e) {
|
||||
loadState = new PluginLoadState(PluginLoadStateType.INVALID_PLUGIN, e.toString());
|
||||
}
|
||||
switch (loadState.getStateType()) {
|
||||
case INVALID_DESCRIPTION: {
|
||||
TLocale.sendTo(sender, "COMMANDS.TPLUGIN.LOAD.INVALID-DESCRIPTION");
|
||||
break;
|
||||
}
|
||||
case INVALID_PLUGIN: {
|
||||
TLocale.sendTo(sender, "COMMANDS.TPLUGIN.LOAD.INVALID-PLUGIN", name, loadState.getMessage());
|
||||
break;
|
||||
}
|
||||
case FILE_NOT_FOUND: {
|
||||
TLocale.sendTo(sender, "COMMANDS.TPLUGIN.LOAD.FILE-NOT-FOUND", name);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
TLocale.sendTo(sender, "COMMANDS.TPLUGIN.LOAD.LOAD-SUCCESS", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@CommandRegister(priority = 2)
|
||||
BaseSubCommand unload = new BaseSubCommand() {
|
||||
|
||||
@Override
|
||||
public String getLabel() {
|
||||
return "unload";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return TLocale.asString("COMMANDS.TPLUGIN.UNLOAD.DESCRIPTION");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandArgument[] getArguments() {
|
||||
return new CommandArgument[] {new CommandArgument(TLocale.asString("COMMANDS.TPLUGIN.UNLOAD.ARGUMENTS.0"), true, () -> {
|
||||
return java.util.Arrays.stream(Bukkit.getPluginManager().getPlugins()).map(Plugin::getName).collect(Collectors.toList());
|
||||
})};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
String name = ArrayUtil.arrayJoin(args, 0);
|
||||
Plugin plugin = PluginUtils.getPluginByName(name);
|
||||
if (plugin == null) {
|
||||
TLocale.sendTo(sender, "COMMANDS.TPLUGIN.UNLOAD.INVALID-PLUGIN", name);
|
||||
} else if (PluginUtils.isIgnored(plugin)) {
|
||||
TLocale.sendTo(sender, "COMMANDS.TPLUGIN.UNLOAD.INVALID-PLUGIN-IGNORED", name);
|
||||
} else {
|
||||
PluginUnloadState unloadState;
|
||||
try {
|
||||
unloadState = PluginUtils.unload(plugin);
|
||||
} catch (Exception e) {
|
||||
unloadState = new PluginUnloadState(true, e.toString());
|
||||
}
|
||||
if (unloadState.isFailed()) {
|
||||
TLocale.sendTo(sender, "COMMANDS.TPLUGIN.UNLOAD.UNLOAD-FAIL", name, unloadState.getMessage());
|
||||
} else {
|
||||
TLocale.sendTo(sender, "COMMANDS.TPLUGIN.UNLOAD.UNLOAD-SUCCESS", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@CommandRegister(priority = 3)
|
||||
BaseSubCommand reload = new BaseSubCommand() {
|
||||
|
||||
@Override
|
||||
public String getLabel() {
|
||||
return "reload";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return TLocale.asString("COMMANDS.TPLUGIN.RELOAD.DESCRIPTION");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandArgument[] getArguments() {
|
||||
return new CommandArgument[] {new CommandArgument(TLocale.asString("COMMANDS.TPLUGIN.RELOAD.ARGUMENTS.0"), true, () -> {
|
||||
return Arrays.stream(Bukkit.getPluginManager().getPlugins()).map(Plugin::getName).collect(Collectors.toList());
|
||||
})};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
String name = ArrayUtil.arrayJoin(args, 0);
|
||||
Plugin plugin = PluginUtils.getPluginByName(name);
|
||||
if (plugin == null) {
|
||||
TLocale.sendTo(sender, "COMMANDS.TPLUGIN.RELOAD.INVALID-PLUGIN", name);
|
||||
} else if (PluginUtils.isIgnored(plugin)) {
|
||||
TLocale.sendTo(sender, "COMMANDS.TPLUGIN.RELOAD.INVALID-PLUGIN-IGNORED", name);
|
||||
} else {
|
||||
TabooLibAPI.dispatchCommand(sender, "taboolibplugin unload " + plugin.getName());
|
||||
TabooLibAPI.dispatchCommand(sender, "taboolibplugin load " + plugin.getName());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@CommandRegister(priority = 4)
|
||||
BaseSubCommand info = new BaseSubCommand() {
|
||||
|
||||
@Override
|
||||
public String getLabel() {
|
||||
return "info";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return TLocale.asString("COMMANDS.TPLUGIN.INFO.DESCRIPTION");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandArgument[] getArguments() {
|
||||
return new CommandArgument[] {new CommandArgument(TLocale.asString("COMMANDS.TPLUGIN.INFO.ARGUMENTS.0"), true, () -> {
|
||||
return Arrays.stream(Bukkit.getPluginManager().getPlugins()).map(Plugin::getName).collect(Collectors.toList());
|
||||
})};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
String name = ArrayUtil.arrayJoin(args, 0);
|
||||
Plugin plugin = PluginUtils.getPluginByName(name);
|
||||
if (plugin == null) {
|
||||
TLocale.sendTo(sender, "COMMANDS.TPLUGIN.INFO.INVALID-PLUGIN", name);
|
||||
} else {
|
||||
try {
|
||||
TLocale.sendTo(sender, "COMMANDS.TPLUGIN.INFO.INFO-PLUGIN",
|
||||
plugin.getName(),
|
||||
String.valueOf(plugin.getDescription().getDescription()),
|
||||
String.valueOf(plugin.getDescription().getAuthors()),
|
||||
String.valueOf(plugin.getDescription().getDepend()),
|
||||
String.valueOf(plugin.getDescription().getSoftDepend()),
|
||||
String.valueOf(plugin.getDescription().getMain()),
|
||||
String.valueOf(plugin.getDescription().getVersion()),
|
||||
String.valueOf(plugin.getDescription().getWebsite()),
|
||||
String.valueOf(plugin.getDescription().getCommands() == null ? "" : plugin.getDescription().getCommands().keySet()));
|
||||
} catch (Exception e) {
|
||||
TLocale.sendTo(sender, "COMMANDS.TPLUGIN.INFO.INVALID-DESCRIPTION", name, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@CommandRegister(priority = 5)
|
||||
BaseSubCommand list = new BaseSubCommand() {
|
||||
|
||||
@Override
|
||||
public String getLabel() {
|
||||
return "list";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return TLocale.asString("COMMANDS.TPLUGIN.LIST.DESCRIPTION");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandArgument[] getArguments() {
|
||||
return new CommandArgument[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
List<String> pluginList = Arrays.stream(Bukkit.getPluginManager().getPlugins()).map(PluginUtils::getFormattedName).sorted(String.CASE_INSENSITIVE_ORDER).collect(Collectors.toList());
|
||||
TLocale.sendTo(sender, "COMMANDS.TPLUGIN.LIST.LIST-PLUGIN", String.valueOf(Bukkit.getPluginManager().getPlugins().length), Joiner.on(", ").join(pluginList));
|
||||
}
|
||||
};
|
||||
|
||||
// *********************************
|
||||
//
|
||||
// Private Methods
|
||||
//
|
||||
// *********************************
|
||||
|
||||
private boolean isPluginCommand(String label) {
|
||||
return "info".equalsIgnoreCase(label) || "load".equalsIgnoreCase(label) || "unload".equalsIgnoreCase(label) || "reload".equalsIgnoreCase(label);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package io.izzel.taboolib.listener;
|
||||
|
||||
import io.izzel.taboolib.module.inject.TListener;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import pw.yumc.Yum.events.PluginNetworkEvent;
|
||||
|
||||
/**
|
||||
* @author sky
|
||||
* @since 2018年2月23日 下午11:10:03
|
||||
*/
|
||||
@TListener(depend = "YUM")
|
||||
public class ListenerNetWork implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onNetWork(PluginNetworkEvent e) {
|
||||
if (e.getPlugin() != null && e.getPlugin().getName().equals("TabooLib")) {
|
||||
e.setCancelled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package io.izzel.taboolib.listener;
|
||||
|
||||
import io.izzel.taboolib.TabooLibAPI;
|
||||
import io.izzel.taboolib.Version;
|
||||
import io.izzel.taboolib.module.inject.TListener;
|
||||
import io.izzel.taboolib.module.item.Items;
|
||||
import io.izzel.taboolib.module.logger.TLogger;
|
||||
import io.izzel.taboolib.module.tellraw.TellrawJson;
|
||||
import io.izzel.taboolib.origin.database.PlayerDataManager;
|
||||
import io.izzel.taboolib.origin.database.PluginDataManager;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
import org.bukkit.event.server.ServerCommandEvent;
|
||||
|
||||
/**
|
||||
* @author sky
|
||||
*/
|
||||
@TListener
|
||||
public class ListenerPlayerCommand implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void cmd(ServerCommandEvent e) {
|
||||
if (e.getCommand().equalsIgnoreCase("saveFiles")) {
|
||||
if (Version.isAfter(Version.v1_8)) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
PluginDataManager.saveAllCaches();
|
||||
PlayerDataManager.saveAllCaches(true, false);
|
||||
TLogger.getGlobalLogger().info("Successfully.");
|
||||
} else if (e.getCommand().equalsIgnoreCase("tDebug")) {
|
||||
if (Version.isAfter(Version.v1_8)) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
if (TabooLibAPI.isDebug()) {
|
||||
TabooLibAPI.setDebug(false);
|
||||
TLogger.getGlobalLogger().info("&cDisabled.");
|
||||
} else {
|
||||
TabooLibAPI.setDebug(true);
|
||||
TLogger.getGlobalLogger().info("&aEnabled.");
|
||||
}
|
||||
} else if (e.getCommand().equalsIgnoreCase("tExceptionEvent")) {
|
||||
e.setCancelled(true);
|
||||
throw new IllegalStateException("TabooLib Example Exception");
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void cmd(PlayerCommandPreprocessEvent e) {
|
||||
if (e.getMessage().equals("/tellrawTest") && e.getPlayer().hasPermission("taboolib.tellraw")) {
|
||||
e.setCancelled(true);
|
||||
TellrawJson.create()
|
||||
.append("§8[§3§lTabooLib§8] §7TellrawJson Test: §f[")
|
||||
.append(Items.getName(e.getPlayer().getItemInHand())).hoverItem(e.getPlayer().getItemInHand())
|
||||
.append("§f]")
|
||||
.send(e.getPlayer());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package io.izzel.taboolib.listener;
|
||||
|
||||
import io.izzel.taboolib.module.inject.TListener;
|
||||
import io.izzel.taboolib.origin.event.PlayerJumpEvent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
@TListener
|
||||
public class ListenerPlayerJump implements Listener {
|
||||
|
||||
public HashMap<Player, Long> cooldown = new HashMap<>();
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void onJump(PlayerMoveEvent event) {
|
||||
if ((!event.getPlayer().isFlying()) && (event.getPlayer().getGameMode() != GameMode.CREATIVE) && (event.getFrom().getY() + 0.5D != event.getTo().getY()) && (event.getFrom().getY() + 0.419D < event.getTo().getY())) {
|
||||
Location loc = event.getFrom();
|
||||
loc.setY(event.getFrom().getY() - 1.0D);
|
||||
if (loc.getBlock().getType() != Material.AIR) {
|
||||
if (!this.cooldown.containsKey(event.getPlayer())) {
|
||||
this.cooldown.put(event.getPlayer(), System.currentTimeMillis() + 350L);
|
||||
PlayerJumpEvent evt = new PlayerJumpEvent(event.isCancelled(), event.getPlayer());
|
||||
Bukkit.getPluginManager().callEvent(evt);
|
||||
if (evt.isCancelled()) {
|
||||
event.setTo(event.getFrom());
|
||||
}
|
||||
} else if (this.cooldown.get(event.getPlayer()) <= System.currentTimeMillis()) {
|
||||
this.cooldown.put(event.getPlayer(), System.currentTimeMillis() + 350L);
|
||||
PlayerJumpEvent evt = new PlayerJumpEvent(event.isCancelled(), event.getPlayer());
|
||||
|
||||
Bukkit.getPluginManager().callEvent(evt);
|
||||
if (evt.isCancelled()) {
|
||||
event.setTo(event.getFrom());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onQuit(PlayerQuitEvent event) {
|
||||
this.cooldown.remove(event.getPlayer());
|
||||
}
|
||||
}
|
||||
172
src/main/scala/io/izzel/taboolib/locale/TLocale.java
Normal file
172
src/main/scala/io/izzel/taboolib/locale/TLocale.java
Normal file
@@ -0,0 +1,172 @@
|
||||
package io.izzel.taboolib.locale;
|
||||
|
||||
import io.izzel.taboolib.TabooLib;
|
||||
import io.izzel.taboolib.module.logger.TLoggerManager;
|
||||
import io.izzel.taboolib.module.nms.NMSHandler;
|
||||
import io.izzel.taboolib.module.tellraw.TellrawCreator;
|
||||
import io.izzel.taboolib.util.Ref;
|
||||
import io.izzel.taboolib.util.Strings;
|
||||
import io.izzel.taboolib.util.chat.ChatColor;
|
||||
import io.izzel.taboolib.util.chat.ComponentSerializer;
|
||||
import io.izzel.taboolib.util.chat.TextComponent;
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author IzzelAliz
|
||||
*/
|
||||
public class TLocale {
|
||||
|
||||
private TLocale() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
static String asString(String path, Class<?> callerClass, String... args) {
|
||||
return TLocaleLoader.asString(Ref.getCallerPlugin(callerClass), path, args);
|
||||
}
|
||||
|
||||
static List<String> asStringList(String path, Class<?> callerClass, String... args) {
|
||||
return TLocaleLoader.asStringList(Ref.getCallerPlugin(callerClass), path, args);
|
||||
}
|
||||
|
||||
private static void sendTo(String path, CommandSender sender, String[] args, Class<?> callerClass) {
|
||||
TLocaleLoader.sendTo(Ref.getCallerPlugin(callerClass), path, sender, args);
|
||||
}
|
||||
|
||||
public static void sendToConsole(String path, String... args) {
|
||||
Ref.getCallerClass(3).ifPresent(clazz -> sendTo(path, Bukkit.getConsoleSender(), args, clazz));
|
||||
}
|
||||
|
||||
public static void sendTo(CommandSender sender, String path, String... args) {
|
||||
Ref.getCallerClass(3).ifPresent(clazz -> sendTo(path, sender, args, clazz));
|
||||
}
|
||||
|
||||
public static void sendTo(String path, CommandSender sender, String... args) {
|
||||
Ref.getCallerClass(3).ifPresent(clazz -> sendTo(path, sender, args, clazz));
|
||||
}
|
||||
|
||||
public static void broadcast(String path, String... args) {
|
||||
Ref.getCallerClass(3).ifPresent(clazz -> Bukkit.getOnlinePlayers().forEach(player -> sendTo(path, player, args, clazz)));
|
||||
}
|
||||
|
||||
public static String asString(String path, String... args) {
|
||||
try {
|
||||
return asString(path, Ref.getCallerClass(3).orElse(TabooLib.class), args);
|
||||
} catch (Exception e) {
|
||||
TabooLib.getLogger().error(Strings.replaceWithOrder(TabooLib.getInst().getInternal().getString("FETCH-LOCALE-ERROR"), path));
|
||||
TabooLib.getLogger().error(Strings.replaceWithOrder(TabooLib.getInst().getInternal().getString("LOCALE-ERROR-REASON"), e.getMessage()));
|
||||
return "§4<" + path + "§4>";
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> asStringList(String path, String... args) {
|
||||
try {
|
||||
return asStringList(path, Ref.getCallerClass(3).orElse(TabooLib.class), args);
|
||||
} catch (Exception e) {
|
||||
TabooLib.getLogger().error(Strings.replaceWithOrder(TabooLib.getInst().getInternal().getString("LOCALE-ERROR-REASON"), e.getMessage()));
|
||||
return Collections.singletonList("§4<" + path + "§4>");
|
||||
}
|
||||
}
|
||||
|
||||
public static void reload() {
|
||||
Ref.getCallerClass(3).ifPresent(clazz -> TLocaleLoader.load(Ref.getCallerPlugin(clazz), false));
|
||||
}
|
||||
|
||||
public static final class Tellraw extends TLocale {
|
||||
|
||||
public static void send(CommandSender sender, String rawMessage) {
|
||||
if (sender instanceof Player) {
|
||||
TellrawCreator.getAbstractTellraw().sendRawMessage((Player) sender, rawMessage);
|
||||
} else {
|
||||
sender.sendMessage(TextComponent.toLegacyText(ComponentSerializer.parse(rawMessage)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Display extends TLocale {
|
||||
|
||||
public static void sendTitle(Player player, String title, String subTitle) {
|
||||
sendTitle(player, title, subTitle, 10, 20, 10);
|
||||
}
|
||||
|
||||
public static void sendTitle(Player player, String title, String subTitle, int fadein, int stay, int fadeout) {
|
||||
NMSHandler.getHandler().sendTitle(player, title, fadein, stay, fadeout, subTitle, fadein, stay, fadeout);
|
||||
}
|
||||
|
||||
public static void sendActionBar(Player player, String text) {
|
||||
NMSHandler.getHandler().sendActionBar(player, text);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Translate extends TLocale {
|
||||
|
||||
public static boolean isPlaceholderUseDefault() {
|
||||
return TabooLib.getConfig().getBoolean("LOCALE.USE_PAPI", false);
|
||||
}
|
||||
|
||||
public static boolean isPlaceholderPluginEnabled() {
|
||||
return Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null && Bukkit.getPluginManager().getPlugin("PlaceholderAPI").isEnabled();
|
||||
}
|
||||
|
||||
public static String setColored(String args) {
|
||||
return ChatColor.translateAlternateColorCodes('&', args);
|
||||
}
|
||||
|
||||
public static List<String> setColored(List<String> args) {
|
||||
return args.stream().map(var -> ChatColor.translateAlternateColorCodes('&', var)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static String setUncolored(String args) {
|
||||
return ChatColor.stripColor(args);
|
||||
}
|
||||
|
||||
public static List<String> setUncolored(List<String> args) {
|
||||
return args.stream().map(ChatColor::stripColor).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static String setPlaceholders(CommandSender sender, String args) {
|
||||
return isPlaceholderPluginEnabled() ? sender instanceof Player ? PlaceholderAPI.setPlaceholders((Player) sender, args) : args : args;
|
||||
}
|
||||
|
||||
public static List<String> setPlaceholders(CommandSender sender, List<String> args) {
|
||||
return isPlaceholderPluginEnabled() ? sender instanceof Player ? PlaceholderAPI.setPlaceholders((Player) sender, args) : args : args;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Logger extends TLocale {
|
||||
|
||||
public static void info(String path, String... args) {
|
||||
Ref.getCallerClass(3).ifPresent(clazz -> asStringList(path, clazz, args).forEach(locale -> TLoggerManager.getLogger(Ref.getCallerPlugin(clazz)).info(locale)));
|
||||
}
|
||||
|
||||
public static void warn(String path, String... args) {
|
||||
Ref.getCallerClass(3).ifPresent(clazz -> asStringList(path, clazz, args).forEach(locale -> TLoggerManager.getLogger(Ref.getCallerPlugin(clazz)).warn(locale)));
|
||||
}
|
||||
|
||||
public static void error(String path, String... args) {
|
||||
Ref.getCallerClass(3).ifPresent(clazz -> asStringList(path, clazz, args).forEach(locale -> TLoggerManager.getLogger(Ref.getCallerPlugin(clazz)).error(locale)));
|
||||
}
|
||||
|
||||
public static void fatal(String path, String... args) {
|
||||
Ref.getCallerClass(3).ifPresent(clazz -> asStringList(path, clazz, args).forEach(locale -> TLoggerManager.getLogger(Ref.getCallerPlugin(clazz)).fatal(locale)));
|
||||
}
|
||||
|
||||
public static void fine(String path, String... args) {
|
||||
Ref.getCallerClass(3).ifPresent(clazz -> asStringList(path, clazz, args).forEach(locale -> TLoggerManager.getLogger(Ref.getCallerPlugin(clazz)).fine(locale)));
|
||||
}
|
||||
|
||||
public static void finest(String path, String... args) {
|
||||
Ref.getCallerClass(3).ifPresent(clazz -> asStringList(path, clazz, args).forEach(locale -> TLoggerManager.getLogger(Ref.getCallerPlugin(clazz)).finest(locale)));
|
||||
}
|
||||
|
||||
public static void verbose(String path, String... args) {
|
||||
Ref.getCallerClass(3).ifPresent(clazz -> asStringList(path, clazz, args).forEach(locale -> TLoggerManager.getLogger(Ref.getCallerPlugin(clazz)).verbose(locale)));
|
||||
}
|
||||
}
|
||||
}
|
||||
117
src/main/scala/io/izzel/taboolib/locale/TLocaleInstance.java
Normal file
117
src/main/scala/io/izzel/taboolib/locale/TLocaleInstance.java
Normal file
@@ -0,0 +1,117 @@
|
||||
package io.izzel.taboolib.locale;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import io.izzel.taboolib.TabooLib;
|
||||
import io.izzel.taboolib.locale.type.TLocaleText;
|
||||
import io.izzel.taboolib.util.Strings;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ThreadSafe
|
||||
@SuppressWarnings("rawtypes")
|
||||
class TLocaleInstance {
|
||||
|
||||
private final Map<String, List<TLocaleSerialize>> map = new HashMap<>();
|
||||
private final Plugin plugin;
|
||||
private final AtomicInteger latestUpdateNodes = new AtomicInteger();
|
||||
|
||||
TLocaleInstance(Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return map.toString();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
public Map<String, List<TLocaleSerialize>> getMap() {
|
||||
return map;
|
||||
}
|
||||
|
||||
public Plugin getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
public AtomicInteger getLatestUpdateNodes() {
|
||||
return latestUpdateNodes;
|
||||
}
|
||||
|
||||
public void sendTo(String path, CommandSender sender, String... args) {
|
||||
try {
|
||||
map.getOrDefault(path, ImmutableList.of(TLocaleSerialize.getEmpty(path))).forEach(tSender -> {
|
||||
if (Bukkit.isPrimaryThread() || "true".equals(System.getProperty("tlib.forceAsync"))) {
|
||||
tSender.sendTo(sender, args);
|
||||
} else {
|
||||
Bukkit.getScheduler().runTask(plugin, () -> tSender.sendTo(sender, args));
|
||||
}
|
||||
});
|
||||
} catch (Exception | Error e) {
|
||||
TabooLib.getLogger().error(Strings.replaceWithOrder(TabooLib.getInst().getInternal().getString("SEND-LOCALE-ERROR"), path));
|
||||
TabooLib.getLogger().error(Strings.replaceWithOrder(TabooLib.getInst().getInternal().getString("LOCALE-ERROR-REASON"), e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
public String asString(String path, String... args) {
|
||||
return map.getOrDefault(path, ImmutableList.of(TLocaleSerialize.getEmpty(path))).get(0).asString(args);
|
||||
}
|
||||
|
||||
public List<String> asStringList(String path, String... args) {
|
||||
return map.getOrDefault(path, ImmutableList.of(TLocaleSerialize.getEmpty(path))).get(0).asStringList(args);
|
||||
}
|
||||
|
||||
private static boolean isListString(List list) {
|
||||
for (Object o : list) {
|
||||
if (!(o instanceof String)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void load(YamlConfiguration configuration) {
|
||||
load(configuration, false);
|
||||
}
|
||||
|
||||
public void load(YamlConfiguration configuration, boolean cleanup) {
|
||||
int originNodes = map.size();
|
||||
int updateNodes = 0;
|
||||
if (cleanup) {
|
||||
map.clear();
|
||||
}
|
||||
for (String s : configuration.getKeys(true)) {
|
||||
boolean updated = false;
|
||||
Object value = configuration.get(s);
|
||||
if (value instanceof TLocaleSerialize) {
|
||||
updated = map.put(s, Collections.singletonList((TLocaleSerialize) value)) != null;
|
||||
} else if (value instanceof List && !((List) value).isEmpty()) {
|
||||
if (isListString((List) value)) {
|
||||
updated = map.put(s, Collections.singletonList(TLocaleText.of(value))) != null;
|
||||
} else {
|
||||
updated = map.put(s, ((List<?>) value).stream().map(o -> o instanceof TLocaleSerialize ? (TLocaleSerialize) o : TLocaleText.of(String.valueOf(o))).collect(Collectors.toList())) != null;
|
||||
}
|
||||
} else if (!(value instanceof ConfigurationSection)) {
|
||||
String str = String.valueOf(value);
|
||||
updated = map.put(s, Collections.singletonList(str.length() == 0 ? TLocaleSerialize.getEmpty() : TLocaleText.of(str))) != null;
|
||||
}
|
||||
if (updated) {
|
||||
updateNodes++;
|
||||
}
|
||||
}
|
||||
latestUpdateNodes.set(originNodes - updateNodes);
|
||||
}
|
||||
}
|
||||
19
src/main/scala/io/izzel/taboolib/locale/TLocaleSender.java
Normal file
19
src/main/scala/io/izzel/taboolib/locale/TLocaleSender.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package io.izzel.taboolib.locale;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-05-12 13:58
|
||||
*/
|
||||
public interface TLocaleSender {
|
||||
|
||||
void sendTo(CommandSender sender, String... args);
|
||||
|
||||
String asString(String... args);
|
||||
|
||||
List<String> asStringList(String... args);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package io.izzel.taboolib.locale;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-05-12 14:01
|
||||
*/
|
||||
public abstract class TLocaleSerialize implements TLocaleSender, ConfigurationSerializable {
|
||||
|
||||
public static boolean isPlaceholderEnabled(Map<String, Object> map) {
|
||||
Object placeholderObject = map.getOrDefault("papi", TLocale.Translate.isPlaceholderUseDefault());
|
||||
return placeholderObject instanceof Boolean ? (boolean) placeholderObject : placeholderObject instanceof String && "true".equals(placeholderObject);
|
||||
}
|
||||
|
||||
public static String getStringOrDefault(Map<String, Object> map, String path, String def) {
|
||||
Object var = map.getOrDefault(path, def);
|
||||
return var instanceof String ? (String) var : def;
|
||||
}
|
||||
|
||||
public static Integer getIntegerOrDefault(Map<String, Object> map, String path, Integer def) {
|
||||
Object var = map.getOrDefault(path, def);
|
||||
return var instanceof Integer ? (Integer) var : def;
|
||||
}
|
||||
|
||||
public static Double getDoubleOrDefault(Map<String, Object> map, String path, Double def) {
|
||||
Object var = map.getOrDefault(path, def);
|
||||
return var instanceof Double ? (Double) var : def;
|
||||
}
|
||||
|
||||
static TLocaleSerialize getEmpty() {
|
||||
return new TLocaleSerialize() {
|
||||
|
||||
@Override
|
||||
public void sendTo(CommandSender sender, String... args) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> serialize() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static TLocaleSerialize getEmpty(String path) {
|
||||
return new TLocaleSerialize() {
|
||||
|
||||
@Override
|
||||
public Map<String, Object> serialize() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTo(CommandSender sender, String... args) {
|
||||
sender.sendMessage("§8<" + path + "§8>");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString(String... args) {
|
||||
return "§8<" + path + "§8>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> asStringList(String... args) {
|
||||
return Collections.singletonList("§4<" + path + "§4>");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString(String... args) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> asStringList(String... args) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package io.izzel.taboolib.locale.type;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import io.izzel.taboolib.locale.TLocale;
|
||||
import io.izzel.taboolib.locale.TLocaleSerialize;
|
||||
import io.izzel.taboolib.module.compat.PlaceholderHook;
|
||||
import io.izzel.taboolib.util.Strings;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.serialization.SerializableAs;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import java.util.Map;
|
||||
|
||||
@Immutable
|
||||
@SerializableAs("ACTION")
|
||||
public class TLocaleActionBar extends TLocaleSerialize {
|
||||
|
||||
private final String text;
|
||||
private final boolean papi;
|
||||
|
||||
private TLocaleActionBar(String text, boolean papi) {
|
||||
this.text = text;
|
||||
this.papi = papi;
|
||||
}
|
||||
|
||||
public static TLocaleActionBar valueOf(Map<String, Object> map) {
|
||||
String text = ChatColor.translateAlternateColorCodes('&', String.valueOf(map.getOrDefault("text", "Empty Action bar message.")));
|
||||
return new TLocaleActionBar(text, isPlaceholderEnabled(map));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTo(CommandSender sender, String... args) {
|
||||
if (sender instanceof Player) {
|
||||
TLocale.Display.sendActionBar(((Player) sender), replace(sender, text, args));
|
||||
}
|
||||
}
|
||||
|
||||
private String replace(CommandSender sender, String text, String[] args) {
|
||||
String s = Strings.replaceWithOrder(text, args);
|
||||
return papi ? PlaceholderHook.replace(sender, s) : s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString(String... args) {
|
||||
return "ActionBar: [" + text + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> serialize() {
|
||||
Map<String, Object> map = Maps.newHashMap();
|
||||
map.put("text", text);
|
||||
if (papi) {
|
||||
map.put("papi", true);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package io.izzel.taboolib.locale.type;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import io.izzel.taboolib.TabooLib;
|
||||
import io.izzel.taboolib.locale.TLocale;
|
||||
import io.izzel.taboolib.locale.TLocaleSerialize;
|
||||
import io.izzel.taboolib.module.tellraw.TellrawJson;
|
||||
import io.izzel.taboolib.origin.book.BookFormatter;
|
||||
import io.izzel.taboolib.origin.book.builder.BookBuilder;
|
||||
import io.izzel.taboolib.util.Strings;
|
||||
import io.izzel.taboolib.util.chat.ComponentSerializer;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.serialization.SerializableAs;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-05-27 0:05
|
||||
*/
|
||||
@ThreadSafe
|
||||
@SerializableAs("BOOK")
|
||||
public class TLocaleBook extends TLocaleSerialize {
|
||||
|
||||
/*
|
||||
BookTest:
|
||||
- ==: BOOK
|
||||
pages:
|
||||
0:
|
||||
- '第一页内容'
|
||||
- '[ <变量1@page-1> ]'
|
||||
1:
|
||||
- '第二页内容'
|
||||
- '[ <变量2@page-2> ]'
|
||||
args:
|
||||
page-1:
|
||||
hover: '展示内容1'
|
||||
command: '/say %player_name% NB1'
|
||||
page-2:
|
||||
hover: '展示内容2'
|
||||
suggest: '/say %player_name% NB2'
|
||||
*/
|
||||
|
||||
private final List<TellrawJson> pages;
|
||||
private final Map<String, Object> map;
|
||||
private final boolean papi;
|
||||
|
||||
public TLocaleBook(List<TellrawJson> pages, Map<String, Object> map, boolean papi) {
|
||||
this.pages = pages;
|
||||
this.map = map;
|
||||
this.papi = papi;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> serialize() {
|
||||
return Maps.newHashMap(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTo(CommandSender sender, String... args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
return;
|
||||
}
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
BookBuilder bookBuilder = BookFormatter.writtenBook();
|
||||
pages.stream().map(jsonPage -> format(jsonPage, sender, args)).map(ComponentSerializer::parse).forEach(bookBuilder::addPages);
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
BookFormatter.forceOpen((Player) sender, bookBuilder.build());
|
||||
}
|
||||
}.runTask(TabooLib.getPlugin());
|
||||
}
|
||||
}.runTaskAsynchronously(TabooLib.getPlugin());
|
||||
}
|
||||
|
||||
private String format(TellrawJson jsonPage, CommandSender sender, String[] args) {
|
||||
return papi ? TLocale.Translate.setPlaceholders(sender, Strings.replaceWithOrder(jsonPage.toRawMessage(), args)) : Strings.replaceWithOrder(jsonPage.toRawMessage(), args);
|
||||
}
|
||||
|
||||
public static TLocaleBook valueOf(Map<String, Object> map) {
|
||||
Map<String, Object> pages = map.containsKey("pages") ? (Map<String, Object>) map.get("pages") : new HashMap<>();
|
||||
Map<String, Object> section = map.containsKey("args") ? (Map<String, Object>) map.get("args") : new HashMap<>();
|
||||
List<TellrawJson> pageJsonList = pages.values().stream().map(page -> TLocaleJson.formatJson(section, page, TellrawJson.create())).collect(Collectors.toList());
|
||||
return new TLocaleBook(pageJsonList, map, isPlaceholderEnabled(map));
|
||||
}
|
||||
}
|
||||
102
src/main/scala/io/izzel/taboolib/locale/type/TLocaleBossBar.java
Normal file
102
src/main/scala/io/izzel/taboolib/locale/type/TLocaleBossBar.java
Normal file
@@ -0,0 +1,102 @@
|
||||
package io.izzel.taboolib.locale.type;
|
||||
|
||||
import io.izzel.taboolib.locale.TLocale;
|
||||
import io.izzel.taboolib.locale.TLocaleSerialize;
|
||||
import io.izzel.taboolib.util.Strings;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.serialization.SerializableAs;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.NumberConversions;
|
||||
import org.inventivetalent.bossbar.BossBar;
|
||||
import org.inventivetalent.bossbar.BossBarAPI;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-05-27 18:52
|
||||
*/
|
||||
@ThreadSafe
|
||||
@SerializableAs("BAR")
|
||||
public class TLocaleBossBar extends TLocaleSerialize {
|
||||
|
||||
/*
|
||||
BossBar:
|
||||
- ==: BAR
|
||||
text: 'BossBar 血条公告'
|
||||
color: BLUE
|
||||
style: NOTCHED_20
|
||||
progress: 1.0
|
||||
timeout: 20
|
||||
timeout-interval: 2
|
||||
*/
|
||||
|
||||
private final String text;
|
||||
private final BossBarAPI.Color color;
|
||||
private final BossBarAPI.Style style;
|
||||
private final float progress;
|
||||
private final int timeout;
|
||||
private final int timeoutInterval;
|
||||
private final boolean papi;
|
||||
|
||||
public TLocaleBossBar(String text, BossBarAPI.Color color, BossBarAPI.Style style, float progress, int timeout, int timeoutInterval, boolean papi) {
|
||||
this.text = text;
|
||||
this.color = color;
|
||||
this.style = style;
|
||||
this.progress = progress;
|
||||
this.timeout = timeout;
|
||||
this.timeoutInterval = timeoutInterval;
|
||||
this.papi = papi;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTo(CommandSender sender, String... args) {
|
||||
if (Bukkit.getPluginManager().getPlugin("BossBarAPI") == null) {
|
||||
TLocale.Logger.error("LOCALE.BAR-PLUGIN-NOT-FOUND");
|
||||
return;
|
||||
}
|
||||
if (sender instanceof Player) {
|
||||
TextComponent textComponent = new TextComponent(papi ? TLocale.Translate.setPlaceholders(sender, Strings.replaceWithOrder(text, args)) : TLocale.Translate.setColored(Strings.replaceWithOrder(text, args)));
|
||||
BossBar bossBar = BossBarAPI.addBar((Player) sender, textComponent, color, style, progress, timeout, timeoutInterval);
|
||||
} else {
|
||||
sender.sendMessage(text);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> serialize() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static TLocaleBossBar valueOf(Map<String, Object> map) {
|
||||
return new TLocaleBossBar(
|
||||
map.getOrDefault("text", "§4* Invalid Text*").toString(),
|
||||
getColor(String.valueOf(map.get("color"))),
|
||||
getStyle(String.valueOf(map.get("style"))),
|
||||
NumberConversions.toFloat(map.getOrDefault("progress", 1)),
|
||||
NumberConversions.toInt(map.getOrDefault("timeout", 20)),
|
||||
NumberConversions.toInt(map.getOrDefault("timeout-interval", 2)),
|
||||
isPlaceholderEnabled(map));
|
||||
}
|
||||
|
||||
private static BossBarAPI.Color getColor(String color) {
|
||||
try {
|
||||
return BossBarAPI.Color.valueOf(color);
|
||||
} catch (Exception e) {
|
||||
TLocale.Logger.error("LOCALE.BAR-STYLE-IDENTIFICATION-FAILED", e.toString());
|
||||
return BossBarAPI.Color.WHITE;
|
||||
}
|
||||
}
|
||||
|
||||
private static BossBarAPI.Style getStyle(String style) {
|
||||
try {
|
||||
return BossBarAPI.Style.valueOf(style);
|
||||
} catch (Exception e) {
|
||||
TLocale.Logger.error("LOCALE.BAR-COLOR-IDENTIFICATION-FAILED", e.toString());
|
||||
return BossBarAPI.Style.NOTCHED_20;
|
||||
}
|
||||
}
|
||||
}
|
||||
222
src/main/scala/io/izzel/taboolib/locale/type/TLocaleJson.java
Normal file
222
src/main/scala/io/izzel/taboolib/locale/type/TLocaleJson.java
Normal file
@@ -0,0 +1,222 @@
|
||||
package io.izzel.taboolib.locale.type;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import io.izzel.taboolib.TabooLib;
|
||||
import io.izzel.taboolib.locale.TLocale;
|
||||
import io.izzel.taboolib.locale.TLocaleSerialize;
|
||||
import io.izzel.taboolib.module.compat.PlaceholderHook;
|
||||
import io.izzel.taboolib.module.tellraw.TellrawJson;
|
||||
import io.izzel.taboolib.util.Strings;
|
||||
import io.izzel.taboolib.util.Variables;
|
||||
import io.izzel.taboolib.util.chat.*;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.serialization.SerializableAs;
|
||||
import org.bukkit.util.NumberConversions;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
@ThreadSafe
|
||||
@SerializableAs("JSON")
|
||||
public class TLocaleJson extends TLocaleSerialize {
|
||||
|
||||
private static final Pattern pattern = Pattern.compile("<([^<>]*)?@([^<>]*)>");
|
||||
private final List<BaseComponent[]> components;
|
||||
private final boolean papi;
|
||||
private final Map<String, Object> map;
|
||||
|
||||
private TLocaleJson(List<BaseComponent[]> components, boolean papi, Map<String, Object> map) {
|
||||
this.components = ImmutableList.copyOf(components);
|
||||
this.papi = papi;
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
public static TLocaleJson valueOf(Map<String, Object> map) {
|
||||
List<String> textList = getTextList(map.getOrDefault("text", "Empty Node"));
|
||||
|
||||
// 分析 args 并替换
|
||||
Object argsObj = map.get("args");
|
||||
if (argsObj instanceof Map) {
|
||||
Map<String, Object> section = new HashMap<>(((Map<?, ?>) argsObj).size());
|
||||
|
||||
// valueOf(k) 是因为这个键可能加载为一个 Integer 导致 contains(String) 返回 false
|
||||
((Map<?, ?>) argsObj).forEach((k, v) -> section.put(String.valueOf(k), v));
|
||||
List<BaseComponent[]> collect = textList.stream().map(s -> {
|
||||
int index = 0;
|
||||
String[] template = pattern.split(s);
|
||||
Matcher matcher = pattern.matcher(s);
|
||||
// 有可能开头和结尾是替换文本,所以做个特判
|
||||
List<BaseComponent> builder = template.length > index ? new ArrayList<>(Arrays.asList(TextComponent.fromLegacyText(template[index++]))) : new ArrayList<>();
|
||||
while (matcher.find()) {
|
||||
String replace = matcher.group();
|
||||
// 假的 <@>
|
||||
if (replace.length() <= 2) {
|
||||
continue;
|
||||
}
|
||||
// 真的 <@xxx>
|
||||
replace = replace.substring(1, replace.length() - 1);
|
||||
String[] split = replace.split("@");
|
||||
// @ 前面的字符串
|
||||
String text = split.length > 1 ? split[0] : "";
|
||||
// @ 后面的节点名
|
||||
String node = split.length > 1 ? split[1] : split[0];
|
||||
// 如果 args 有这个 xxx
|
||||
if (section.containsKey(node)) {
|
||||
Map<String, Object> arg = (Map<String, Object>) section.get(node);
|
||||
text = TLocale.Translate.setColored(String.valueOf(arg.getOrDefault("text", text)));
|
||||
// 可能有很多个 BaseComponent,于是为每个 component 单独设置各种事件
|
||||
BaseComponent[] component = TextComponent.fromLegacyText(text);
|
||||
arg.forEach((key, value) -> {
|
||||
if (key.equalsIgnoreCase("suggest")) {
|
||||
Arrays.stream(component).forEach(baseComponent -> baseComponent.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, String.valueOf(value))));
|
||||
} else if (key.equalsIgnoreCase("command") || "commands".equalsIgnoreCase(key)) {
|
||||
Arrays.stream(component).forEach(baseComponent -> baseComponent.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, String.valueOf(value))));
|
||||
} else if (key.equalsIgnoreCase("hover")) {
|
||||
Arrays.stream(component).forEach(baseComponent -> baseComponent.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(TLocale.Translate.setColored(String.valueOf(value))).create())));
|
||||
}
|
||||
});
|
||||
// 添加到原来的 list 里面
|
||||
builder.addAll(Arrays.asList(component));
|
||||
} else {
|
||||
// 这个参数节点并没有找到,于是随便放点字符串进去
|
||||
builder.addAll(Arrays.asList(TextComponent.fromLegacyText(text)));
|
||||
TabooLib.getLogger().warn(Strings.replaceWithOrder(TabooLib.getInst().getInternal().getString("MISSING-ARGUMENT"), node));
|
||||
}
|
||||
// 有可能一开头就是 <@xxx>,然后 split 出来就少了一些,于是直接加上
|
||||
if (index < template.length) {
|
||||
builder.addAll(Arrays.asList(TextComponent.fromLegacyText(template[index++])));
|
||||
}
|
||||
}
|
||||
return builder.toArray(new BaseComponent[0]);
|
||||
}).collect(Collectors.toList());
|
||||
return new TLocaleJson(collect, isPlaceholderEnabled(map), map);
|
||||
}
|
||||
return new TLocaleJson(textList.stream().map(TextComponent::fromLegacyText).collect(Collectors.toList()), isPlaceholderEnabled(map), map);
|
||||
}
|
||||
|
||||
private static List<String> getTextList(Object textObj) {
|
||||
if (textObj instanceof List) {
|
||||
return ((List<?>) textObj).stream().map(Object::toString).map(TLocale.Translate::setColored).collect(Collectors.toList());
|
||||
} else if (textObj instanceof String) {
|
||||
return Lists.newArrayList(TLocale.Translate.setColored((String) textObj));
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTo(CommandSender sender, String... args) {
|
||||
components.forEach(comp -> sendRawMessage(sender, replace(comp, sender, args)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString(String... args) {
|
||||
return components.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> serialize() {
|
||||
return Maps.newHashMap(map);
|
||||
}
|
||||
|
||||
private void sendRawMessage(CommandSender sender, BaseComponent[] components) {
|
||||
TLocale.Tellraw.send(sender, ComponentSerializer.toString(components));
|
||||
}
|
||||
|
||||
private List<BaseComponent> replace(List<BaseComponent> component, CommandSender sender, String... args) {
|
||||
return component.stream().map(c -> replace(c, sender, args)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private BaseComponent[] replace(BaseComponent[] component, CommandSender sender, String... args) {
|
||||
BaseComponent[] components = new BaseComponent[component.length];
|
||||
for (int i = 0; i < components.length; i++) {
|
||||
components[i] = replace(component[i].duplicate(), sender, args);
|
||||
}
|
||||
return components;
|
||||
}
|
||||
|
||||
private BaseComponent replace(BaseComponent component, CommandSender sender, String... args) {
|
||||
if (component.getClickEvent() != null) {
|
||||
ClickEvent clickEvent = new ClickEvent(component.getClickEvent().getAction(), replace(sender, component.getClickEvent().getValue(), args));
|
||||
component.setClickEvent(clickEvent);
|
||||
}
|
||||
if (component.getHoverEvent() != null) {
|
||||
HoverEvent hoverEvent = new HoverEvent(component.getHoverEvent().getAction(), replace(component.getHoverEvent().getValue(), sender, args));
|
||||
component.setHoverEvent(hoverEvent);
|
||||
}
|
||||
if (component.getExtra() != null) {
|
||||
component.setExtra(replace(component.getExtra(), sender, args));
|
||||
}
|
||||
if (component instanceof TextComponent) {
|
||||
((TextComponent) component).setText(replace(sender, ((TextComponent) component).getText(), args));
|
||||
}
|
||||
return component;
|
||||
}
|
||||
|
||||
private String replace(CommandSender sender, String text, String[] args) {
|
||||
String s = Strings.replaceWithOrder(text, args);
|
||||
return papi ? PlaceholderHook.replace(sender, s) : s;
|
||||
}
|
||||
|
||||
public static TellrawJson formatJson(Map<String, Object> section, Object textObject, TellrawJson pageJson) {
|
||||
List<String> textList = textObject instanceof List ? (List<String>) textObject : Collections.singletonList(String.valueOf(textObject));
|
||||
// 遍历本页文本
|
||||
for (int i = 0; i < textList.size(); i++) {
|
||||
// 捕捉变量
|
||||
for (Variables.Variable variable : new Variables(TLocale.Translate.setColored(textList.get(i)), pattern).find().getVariableList()) {
|
||||
// 如果是变量
|
||||
if (variable.isVariable()) {
|
||||
String[] split = variable.getText().split("@");
|
||||
// @ 前面的字符串
|
||||
String text = split.length > 1 ? split[0] : "§4* Invalid Text *";
|
||||
// @ 后面的节点名
|
||||
String node = split.length > 1 ? split[1] : null;
|
||||
// 处理变量
|
||||
formatNode(section, pageJson, text, node);
|
||||
} else {
|
||||
pageJson.append(variable.getText());
|
||||
}
|
||||
}
|
||||
if (i + 1 < textList.size()) {
|
||||
pageJson.newLine();
|
||||
}
|
||||
}
|
||||
return pageJson;
|
||||
}
|
||||
|
||||
private static void formatNode(Map<String, Object> section, TellrawJson pageJson, String text, String node) {
|
||||
if (section.containsKey(node)) {
|
||||
try {
|
||||
Map<String, Object> args = (Map<String, Object>) section.get(node);
|
||||
// 文本
|
||||
pageJson.append(args.getOrDefault("text", text).toString());
|
||||
// 功能
|
||||
if (args.containsKey("hover")) {
|
||||
pageJson.hoverText(args.get("hover").toString());
|
||||
}
|
||||
if (args.containsKey("suggest")) {
|
||||
pageJson.clickSuggest(args.get("suggest").toString());
|
||||
}
|
||||
if (args.containsKey("command")) {
|
||||
pageJson.clickCommand(args.get("command").toString());
|
||||
}
|
||||
if (args.containsKey("page")) {
|
||||
pageJson.clickChangePage(NumberConversions.toInt(args.get("page").toString()));
|
||||
}
|
||||
if (args.containsKey("url")) {
|
||||
pageJson.clickOpenURL(args.get("url").toString());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
TLocale.Logger.error("LOCALE.BOOK-ARGUMENTS-IDENTIFICATION-FAILED", e.toString());
|
||||
}
|
||||
} else {
|
||||
pageJson.append("§4* Invalid Argument *");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package io.izzel.taboolib.locale.type;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import io.izzel.taboolib.locale.TLocaleSerialize;
|
||||
import io.izzel.taboolib.origin.lite.Sounds;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.serialization.SerializableAs;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-05-06 14:35
|
||||
*/
|
||||
@Immutable
|
||||
@SerializableAs("ACTION")
|
||||
public class TLocaleSound extends TLocaleSerialize {
|
||||
|
||||
private final List<Sounds> soundPacks;
|
||||
|
||||
public TLocaleSound(List<Sounds> soundPacks) {
|
||||
this.soundPacks = soundPacks;
|
||||
}
|
||||
|
||||
public static TLocaleSound valueOf(Map<String, Object> map) {
|
||||
List<Sounds> soundPacks = new ArrayList<>();
|
||||
Object sounds = map.containsKey("sounds") ? map.get("sounds") : map.getOrDefault("sound", "");
|
||||
if (sounds instanceof List) {
|
||||
soundPacks = ((List<String>) sounds).stream().map(Sounds::new).collect(Collectors.toList());
|
||||
} else {
|
||||
soundPacks.add(new Sounds(sounds.toString()));
|
||||
}
|
||||
return new TLocaleSound(soundPacks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTo(CommandSender sender, String... args) {
|
||||
if (sender instanceof Player) {
|
||||
soundPacks.forEach(x -> x.play((Player) sender));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString(String... args) {
|
||||
return toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "soundPacks=" + "TLocaleSound{" + soundPacks + '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> serialize() {
|
||||
Map<String, Object> map = Maps.newHashMap();
|
||||
if (soundPacks.size() == 1) {
|
||||
map.put("sounds", soundPacks.get(0).toString());
|
||||
} else if (soundPacks.size() > 1) {
|
||||
map.put("sounds", soundPacks.stream().map(Sounds::toString).collect(Collectors.toList()));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}
|
||||
105
src/main/scala/io/izzel/taboolib/locale/type/TLocaleText.java
Normal file
105
src/main/scala/io/izzel/taboolib/locale/type/TLocaleText.java
Normal file
@@ -0,0 +1,105 @@
|
||||
package io.izzel.taboolib.locale.type;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import io.izzel.taboolib.locale.TLocale;
|
||||
import io.izzel.taboolib.locale.TLocaleSerialize;
|
||||
import io.izzel.taboolib.util.Strings;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.serialization.SerializableAs;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Immutable
|
||||
@SerializableAs("TEXT")
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public class TLocaleText extends TLocaleSerialize {
|
||||
|
||||
private final Object text;
|
||||
private final boolean usePlaceholder;
|
||||
|
||||
private TLocaleText(Object text, boolean usePlaceholder) {
|
||||
this.usePlaceholder = usePlaceholder;
|
||||
if (text instanceof String) {
|
||||
this.text = text;
|
||||
} else if (text instanceof List) {
|
||||
this.text = ImmutableList.copyOf(((List) text));
|
||||
} else {
|
||||
throw new IllegalArgumentException("Param 'text' can only be an instance of String or List<String>");
|
||||
}
|
||||
}
|
||||
|
||||
public static TLocaleText of(String s) {
|
||||
return new TLocaleText(TLocale.Translate.setColored(s), TLocale.Translate.isPlaceholderUseDefault());
|
||||
}
|
||||
|
||||
public static TLocaleText of(Object o) {
|
||||
return o instanceof String ? of(((String) o)) : new TLocaleText(o, false);
|
||||
}
|
||||
|
||||
public static TLocaleText valueOf(Map<String, Object> map) {
|
||||
if (map.containsKey("text")) {
|
||||
Object object = map.get("text");
|
||||
if (object instanceof String[]) {
|
||||
return new TLocaleText(Arrays.stream(((String[]) object)).collect(Collectors.toList()), isPlaceholderEnabled(map));
|
||||
} else {
|
||||
return new TLocaleText(Objects.toString(object), isPlaceholderEnabled(map));
|
||||
}
|
||||
}
|
||||
return new TLocaleText("§cError chat message loaded.", TLocale.Translate.isPlaceholderUseDefault());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTo(CommandSender sender, String... args) {
|
||||
if (text instanceof String) {
|
||||
sender.sendMessage(replaceText(sender, Strings.replaceWithOrder((String) text, args)));
|
||||
} else if (text instanceof List) {
|
||||
((List) text).forEach(s -> sender.sendMessage(replaceText(sender, Strings.replaceWithOrder(String.valueOf(s), args))));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString(String... args) {
|
||||
return Strings.replaceWithOrder(TLocale.Translate.setColored(objectToString(text)), args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> asStringList(String... args) {
|
||||
if (text instanceof List) {
|
||||
return ((List<String>) text).stream().map(x -> Strings.replaceWithOrder(TLocale.Translate.setColored(x), args)).collect(Collectors.toList());
|
||||
} else {
|
||||
return Collections.singletonList(asString(args));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (text instanceof String[]) {
|
||||
return Arrays.toString((String[]) text);
|
||||
} else {
|
||||
return text.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> serialize() {
|
||||
return usePlaceholder ? Maps.newHashMap(ImmutableMap.of("text", text, "papi", true)) : Maps.newHashMap(ImmutableMap.of("text", text));
|
||||
}
|
||||
|
||||
private String replaceText(CommandSender sender, String args) {
|
||||
return usePlaceholder ? TLocale.Translate.setPlaceholders(sender, args) : TLocale.Translate.setColored(args);
|
||||
}
|
||||
|
||||
private String objectToString(Object text) {
|
||||
if (text instanceof String) {
|
||||
return ((String) text);
|
||||
} else {
|
||||
StringJoiner joiner = new StringJoiner("\n");
|
||||
((List<String>) text).forEach(joiner::add);
|
||||
return joiner.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package io.izzel.taboolib.locale.type;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import io.izzel.taboolib.locale.TLocale;
|
||||
import io.izzel.taboolib.locale.TLocaleSerialize;
|
||||
import io.izzel.taboolib.util.Strings;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.serialization.SerializableAs;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Bkm016
|
||||
* @since 2018-04-22
|
||||
*/
|
||||
|
||||
@Immutable
|
||||
@SerializableAs("TITLE")
|
||||
public class TLocaleTitle extends TLocaleSerialize {
|
||||
|
||||
private final String title;
|
||||
private final String subtitle;
|
||||
private final int fadein;
|
||||
private final int fadeout;
|
||||
private final int stay;
|
||||
|
||||
private boolean usePlaceholder;
|
||||
|
||||
private TLocaleTitle(String title, String subString, int fadein, int fadeout, int stay, boolean usePlaceholder) {
|
||||
this.title = title;
|
||||
this.subtitle = subString;
|
||||
this.fadein = fadein;
|
||||
this.fadeout = fadeout;
|
||||
this.stay = stay;
|
||||
this.usePlaceholder = usePlaceholder;
|
||||
}
|
||||
|
||||
public static TLocaleTitle valueOf(Map<String, Object> map) {
|
||||
TLocaleTitle title;
|
||||
try {
|
||||
title = new TLocaleTitle(getStringOrDefault(map, "title", ""), getStringOrDefault(map, "subtitle", ""), getIntegerOrDefault(map, "fadein", 10), getIntegerOrDefault(map, "fadeout", 10), getIntegerOrDefault(map, "stay", 10), isPlaceholderEnabled(map));
|
||||
} catch (Exception e) {
|
||||
title = new TLocaleTitle("Empty Title message.", e.getMessage(), 10, 20, 10, false);
|
||||
}
|
||||
return title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTo(CommandSender sender, String... args) {
|
||||
if (sender instanceof Player) {
|
||||
TLocale.Display.sendTitle((Player) sender, replaceText(sender, Strings.replaceWithOrder(title, args)), replaceText(sender, Strings.replaceWithOrder(subtitle, args)), fadein, stay, fadeout);
|
||||
} else {
|
||||
TLocale.Logger.error("LOCALE.TITLE-SEND-TO-NON-PLAYER", asString(args));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString(String... args) {
|
||||
return Strings.replaceWithOrder(Strings.replaceWithOrder("TITLE: [title: ''{0}'', subtitle: ''{1}'', fadeIn: {2}, fadeOut: {3}]", title, subtitle, fadein, fadeout), args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return asString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> serialize() {
|
||||
HashMap<String, Object> map = Maps.newHashMap();
|
||||
map.put("papi", usePlaceholder);
|
||||
map.put("title", title);
|
||||
map.put("subtitle", subtitle);
|
||||
map.put("fadein", fadein);
|
||||
map.put("fadeout", fadeout);
|
||||
map.put("stay", stay);
|
||||
return map;
|
||||
}
|
||||
|
||||
private String replaceText(CommandSender sender, String text, String... args) {
|
||||
return usePlaceholder ? TLocale.Translate.setPlaceholders(sender, text) : TLocale.Translate.setColored(text);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package io.izzel.taboolib.module.ai;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-09-21 13:06
|
||||
*/
|
||||
public interface PathfinderCreator {
|
||||
|
||||
Object createPathfinderGoal(SimpleAi ai);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package io.izzel.taboolib.module.ai;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-09-20 20:47
|
||||
*/
|
||||
public abstract class PathfinderExecutor {
|
||||
|
||||
public abstract Object getEntityInsentient(LivingEntity entity);
|
||||
|
||||
public abstract Object getNavigation(LivingEntity entity);
|
||||
|
||||
public abstract Object getControllerJump(LivingEntity entity);
|
||||
|
||||
public abstract Object getControllerMove(LivingEntity entity);
|
||||
|
||||
public abstract Object getControllerLook(LivingEntity entity);
|
||||
|
||||
public abstract Object getGoalSelector(LivingEntity entity);
|
||||
|
||||
public abstract Object getTargetSelector(LivingEntity entity);
|
||||
|
||||
public abstract Object getPathEntity(LivingEntity entity);
|
||||
|
||||
public abstract void setPathEntity(LivingEntity entity, Object pathEntity);
|
||||
|
||||
public abstract void setGoalAi(LivingEntity entity, SimpleAi ai, int priority);
|
||||
|
||||
public abstract void setTargetAi(LivingEntity entity, SimpleAi ai, int priority);
|
||||
|
||||
public abstract void clearGoalAi(LivingEntity entity);
|
||||
|
||||
public abstract void clearTargetAi(LivingEntity entity);
|
||||
|
||||
public abstract Iterable getGoalAi(LivingEntity entity);
|
||||
|
||||
public abstract Iterable getTargetAi(LivingEntity entity);
|
||||
|
||||
public abstract void setGoalAi(LivingEntity entity, Iterable ai);
|
||||
|
||||
public abstract void setTargetAi(LivingEntity entity, Iterable ai);
|
||||
|
||||
public abstract boolean navigationMove(LivingEntity entity, Location location);
|
||||
|
||||
public abstract boolean navigationMove(LivingEntity entity, Location location, double speed);
|
||||
|
||||
public abstract boolean navigationMove(LivingEntity entity, LivingEntity target);
|
||||
|
||||
public abstract boolean navigationMove(LivingEntity entity, LivingEntity target, double speed);
|
||||
|
||||
public abstract boolean navigationReach(LivingEntity entity);
|
||||
|
||||
public abstract void controllerLookAt(LivingEntity entity, Location target);
|
||||
|
||||
public abstract void controllerLookAt(LivingEntity entity, Entity target);
|
||||
|
||||
public abstract void controllerJumpReady(LivingEntity entity);
|
||||
|
||||
public abstract boolean controllerJumpCurrent(LivingEntity entity);
|
||||
|
||||
public abstract void setFollowRange(LivingEntity entity, double value);
|
||||
}
|
||||
23
src/main/scala/io/izzel/taboolib/module/ai/SimpleAi.java
Normal file
23
src/main/scala/io/izzel/taboolib/module/ai/SimpleAi.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package io.izzel.taboolib.module.ai;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-09-19 19:42
|
||||
*/
|
||||
public abstract class SimpleAi {
|
||||
|
||||
public abstract boolean shouldExecute();
|
||||
|
||||
public boolean continueExecute() {
|
||||
return shouldExecute();
|
||||
}
|
||||
|
||||
public void startTask() {
|
||||
}
|
||||
|
||||
public void resetTask() {
|
||||
}
|
||||
|
||||
public void updateTask() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package io.izzel.taboolib.module.ai;
|
||||
|
||||
import io.izzel.taboolib.module.inject.TFunction;
|
||||
import io.izzel.taboolib.module.lite.SimpleVersionControl;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-09-19 20:31
|
||||
*/
|
||||
@TFunction(enable = "init")
|
||||
public class SimpleAiSelector {
|
||||
|
||||
private static PathfinderCreator internalPathfinderCreator;
|
||||
private static PathfinderExecutor internalPathfinderExecutor;
|
||||
|
||||
static void init() {
|
||||
try {
|
||||
internalPathfinderCreator = (PathfinderCreator) SimpleVersionControl.createNMS("io.izzel.taboolib.module.ai.internal.InternalPathfinderCreator").translate().newInstance();
|
||||
internalPathfinderExecutor = (PathfinderExecutor) SimpleVersionControl.createNMS("io.izzel.taboolib.module.ai.internal.InternalPathfinderExecutor").translate().newInstance();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// *********************************
|
||||
//
|
||||
// Getter and Setter
|
||||
//
|
||||
// *********************************
|
||||
|
||||
public static PathfinderExecutor getExecutor() {
|
||||
return internalPathfinderExecutor;
|
||||
}
|
||||
|
||||
public static PathfinderCreator getCreator() {
|
||||
return internalPathfinderCreator;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package io.izzel.taboolib.module.ai.internal;
|
||||
|
||||
import io.izzel.taboolib.module.ai.PathfinderCreator;
|
||||
import io.izzel.taboolib.module.ai.SimpleAi;
|
||||
|
||||
/**
|
||||
* 该类仅用作生成 ASM 代码,无任何意义
|
||||
*
|
||||
* @Author sky
|
||||
* @Since 2018-09-19 22:31
|
||||
*/
|
||||
public class InternalPathfinderCreator extends net.minecraft.server.v1_8_R3.PathfinderGoal implements PathfinderCreator {
|
||||
|
||||
private SimpleAi simpleAI;
|
||||
|
||||
public InternalPathfinderCreator() {
|
||||
}
|
||||
|
||||
public InternalPathfinderCreator(SimpleAi ai) {
|
||||
this.simpleAI = ai;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createPathfinderGoal(SimpleAi ai) {
|
||||
return new InternalPathfinderCreator(ai);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean a() {
|
||||
return simpleAI.shouldExecute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean b() {
|
||||
return simpleAI.continueExecute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void c() {
|
||||
simpleAI.startTask();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void d() {
|
||||
simpleAI.resetTask();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void e() {
|
||||
simpleAI.updateTask();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
package io.izzel.taboolib.module.ai.internal;
|
||||
|
||||
import io.izzel.taboolib.module.ai.PathfinderExecutor;
|
||||
import io.izzel.taboolib.module.ai.SimpleAi;
|
||||
import io.izzel.taboolib.module.ai.SimpleAiSelector;
|
||||
import io.izzel.taboolib.module.lite.SimpleReflection;
|
||||
import net.minecraft.server.v1_8_R3.*;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 该类仅用作生成 ASM 代码,无任何意义
|
||||
*
|
||||
* @Author sky
|
||||
* @Since 2018-09-20 20:57
|
||||
*/
|
||||
public class InternalPathfinderExecutor extends PathfinderExecutor {
|
||||
|
||||
private Field pathEntity;
|
||||
private Field pathfinderGoalSelectorSet;
|
||||
private Field controllerJumpCurrent;
|
||||
|
||||
public InternalPathfinderExecutor() {
|
||||
try {
|
||||
SimpleReflection.saveField(PathfinderGoalSelector.class);
|
||||
SimpleReflection.saveField(ControllerJump.class);
|
||||
pathfinderGoalSelectorSet =SimpleReflection.getField(PathfinderGoalSelector.class, "b");
|
||||
controllerJumpCurrent = SimpleReflection.getField(ControllerJump.class, "a");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
SimpleReflection.saveField(NavigationAbstract.class);
|
||||
for (Field field : SimpleReflection.getFields(NavigationAbstract.class).values()) {
|
||||
if (field.getType().equals(PathEntity.class)) {
|
||||
pathEntity = field;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getEntityInsentient(LivingEntity entity) {
|
||||
return ((CraftEntity) entity).getHandle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getNavigation(LivingEntity entity) {
|
||||
return ((EntityInsentient) getEntityInsentient(entity)).getNavigation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getControllerJump(LivingEntity entity) {
|
||||
return ((EntityInsentient) getEntityInsentient(entity)).getControllerJump();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getControllerMove(LivingEntity entity) {
|
||||
return ((EntityInsentient) getEntityInsentient(entity)).getControllerMove();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getControllerLook(LivingEntity entity) {
|
||||
return ((EntityInsentient) getEntityInsentient(entity)).getControllerLook();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getGoalSelector(LivingEntity entity) {
|
||||
return ((EntityInsentient) getEntityInsentient(entity)).goalSelector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTargetSelector(LivingEntity entity) {
|
||||
return ((EntityInsentient) getEntityInsentient(entity)).targetSelector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPathEntity(LivingEntity entity) {
|
||||
try {
|
||||
return pathEntity.get(getNavigation(entity));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPathEntity(LivingEntity entity, Object pathEntity) {
|
||||
try {
|
||||
this.pathEntity.set(getNavigation(entity), pathEntity);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGoalAi(LivingEntity entity, SimpleAi ai, int priority) {
|
||||
((EntityInsentient) getEntityInsentient(entity)).goalSelector.a(priority, (PathfinderGoal) SimpleAiSelector.getCreator().createPathfinderGoal(ai));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTargetAi(LivingEntity entity, SimpleAi ai, int priority) {
|
||||
((EntityInsentient) getEntityInsentient(entity)).targetSelector.a(priority, (PathfinderGoal) SimpleAiSelector.getCreator().createPathfinderGoal(ai));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearGoalAi(LivingEntity entity) {
|
||||
try {
|
||||
((Collection) pathfinderGoalSelectorSet.get(((EntityInsentient) getEntityInsentient(entity)).goalSelector)).clear();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearTargetAi(LivingEntity entity) {
|
||||
try {
|
||||
((Collection) pathfinderGoalSelectorSet.get(((EntityInsentient) getEntityInsentient(entity)).targetSelector)).clear();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable getGoalAi(LivingEntity entity) {
|
||||
try {
|
||||
return ((Collection) pathfinderGoalSelectorSet.get(((EntityInsentient) getEntityInsentient(entity)).goalSelector));
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable getTargetAi(LivingEntity entity) {
|
||||
try {
|
||||
return ((Collection) pathfinderGoalSelectorSet.get(((EntityInsentient) getEntityInsentient(entity)).targetSelector));
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGoalAi(LivingEntity entity, Iterable ai) {
|
||||
try {
|
||||
pathfinderGoalSelectorSet.set(((EntityInsentient) getEntityInsentient(entity)).goalSelector, ai);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTargetAi(LivingEntity entity, Iterable ai) {
|
||||
try {
|
||||
pathfinderGoalSelectorSet.set(((EntityInsentient) getEntityInsentient(entity)).targetSelector, ai);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean navigationMove(LivingEntity entity, Location location) {
|
||||
return navigationMove(entity, location, 0.6);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean navigationMove(LivingEntity entity, Location location, double speed) {
|
||||
return ((Navigation) getNavigation(entity)).a(location.getX(), location.getY(), location.getZ(), speed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean navigationMove(LivingEntity entity, LivingEntity target) {
|
||||
return navigationMove(entity, target, 0.6);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean navigationMove(LivingEntity entity, LivingEntity target, double speed) {
|
||||
return ((Navigation) getNavigation(entity)).a(((CraftEntity) target).getHandle(), speed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean navigationReach(LivingEntity entity) {
|
||||
Object pathEntity = getPathEntity(entity);
|
||||
return pathEntity == null || ((PathEntity) pathEntity).b();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void controllerLookAt(LivingEntity entity, Location target) {
|
||||
((ControllerLook) getControllerLook(entity)).a(target.getX(), target.getY(), target.getZ(), 10, 40);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void controllerLookAt(LivingEntity entity, Entity target) {
|
||||
((ControllerLook) getControllerLook(entity)).a(((CraftEntity) target).getHandle(), 10, 40);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void controllerJumpReady(LivingEntity entity) {
|
||||
((ControllerJump) getControllerJump(entity)).a();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean controllerJumpCurrent(LivingEntity entity) {
|
||||
try {
|
||||
return controllerJumpCurrent.getBoolean(getControllerJump(entity));
|
||||
} catch (Exception ignored) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFollowRange(LivingEntity entity, double value) {
|
||||
((EntityInsentient) getEntityInsentient(entity)).getAttributeInstance(GenericAttributes.FOLLOW_RANGE).setValue(value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package io.izzel.taboolib.module.command;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-08-23 20:34
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface TCommand {
|
||||
|
||||
String name();
|
||||
|
||||
String permission() default "";
|
||||
|
||||
String permissionMessage() default "";
|
||||
|
||||
String description() default "";
|
||||
|
||||
String usage() default "";
|
||||
|
||||
String[] aliases() default "";
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
package io.izzel.taboolib.module.command;
|
||||
|
||||
import io.izzel.taboolib.TabooLibAPI;
|
||||
import io.izzel.taboolib.locale.TLocale;
|
||||
import io.izzel.taboolib.module.command.base.BaseMainCommand;
|
||||
import io.izzel.taboolib.module.inject.TFunction;
|
||||
import io.izzel.taboolib.module.lite.SimpleReflection;
|
||||
import io.izzel.taboolib.util.ArrayUtil;
|
||||
import io.izzel.taboolib.util.Files;
|
||||
import io.izzel.taboolib.util.Reflection;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.*;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.SimplePluginManager;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-05-23 2:43
|
||||
*/
|
||||
@TFunction(enable = "init")
|
||||
public class TCommandHandler {
|
||||
|
||||
private static SimpleCommandMap commandMap;
|
||||
private static Map<String, Command> knownCommands;
|
||||
|
||||
static void init() {
|
||||
SimpleReflection.saveField(SimplePluginManager.class, "commandMap");
|
||||
SimpleReflection.saveField(SimpleCommandMap.class, "knownCommands");
|
||||
commandMap = (SimpleCommandMap) SimpleReflection.getFieldValue(SimplePluginManager.class, Bukkit.getPluginManager(), "commandMap");
|
||||
knownCommands = (Map<String, Command>) SimpleReflection.getFieldValue(SimpleCommandMap.class, commandMap, "knownCommands");
|
||||
}
|
||||
|
||||
public static boolean registerPluginCommand(Plugin plugin, String command, CommandExecutor commandExecutor) {
|
||||
return registerPluginCommand(plugin, command, "", "/" + command, new ArrayList<>(), null, null, commandExecutor, null);
|
||||
}
|
||||
|
||||
public static boolean registerPluginCommand(Plugin plugin, String command, CommandExecutor commandExecutor, TabCompleter tabCompleter) {
|
||||
return registerPluginCommand(plugin, command, "", "/" + command, new ArrayList<>(), null, null, commandExecutor, tabCompleter);
|
||||
}
|
||||
|
||||
public static boolean registerPluginCommand(Plugin plugin, String command, String description, CommandExecutor commandExecutor, TabCompleter tabCompleter) {
|
||||
return registerPluginCommand(plugin, command, description, "/" + command, new ArrayList<>(), null, null, commandExecutor, tabCompleter);
|
||||
}
|
||||
|
||||
public static boolean registerPluginCommand(Plugin plugin, String command, String description, String usage, CommandExecutor commandExecutor, TabCompleter tabCompleter) {
|
||||
return registerPluginCommand(plugin, command, description, usage, new ArrayList<>(), null, null, commandExecutor, tabCompleter);
|
||||
}
|
||||
|
||||
public static boolean registerPluginCommand(Plugin plugin, String command, String description, String usage, List<String> aliases, CommandExecutor commandExecutor, TabCompleter tabCompleter) {
|
||||
return registerPluginCommand(plugin, command, description, usage, aliases, null, null, commandExecutor, tabCompleter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取插件注册的命令
|
||||
*/
|
||||
public static Command getPluginCommand(String command) {
|
||||
return commandMap.getCommand(command);
|
||||
}
|
||||
|
||||
/**
|
||||
* 向服务端动态注册命令
|
||||
*
|
||||
* @param plugin 所属插件
|
||||
* @param command 命令名称
|
||||
* @param description 命令描述
|
||||
* @param usage 命令用法
|
||||
* @param aliases 别名
|
||||
* @param permission 权限
|
||||
* @param permissionMessage 权限提示
|
||||
* @param commandExecutor 命令执行器
|
||||
* @param tabCompleter 补全执行器
|
||||
* @return 注册结果(boolean)
|
||||
*/
|
||||
public static boolean registerPluginCommand(Plugin plugin, String command, String description, String usage, List<String> aliases, String permission, String permissionMessage, CommandExecutor commandExecutor, TabCompleter tabCompleter) {
|
||||
try {
|
||||
Constructor<PluginCommand> constructor = PluginCommand.class.getDeclaredConstructor(String.class, Plugin.class);
|
||||
constructor.setAccessible(true);
|
||||
PluginCommand pluginCommand = constructor.newInstance(command, plugin);
|
||||
pluginCommand.setExecutor(commandExecutor);
|
||||
pluginCommand.setTabCompleter(tabCompleter);
|
||||
Reflection.setValue(pluginCommand, pluginCommand.getClass().getSuperclass(), true, "description", description);
|
||||
Reflection.setValue(pluginCommand, pluginCommand.getClass().getSuperclass(), true, "usageMessage", usage);
|
||||
Reflection.setValue(pluginCommand, pluginCommand.getClass().getSuperclass(), true, "aliases", aliases.stream().map(String::toLowerCase).collect(Collectors.toList()));
|
||||
Reflection.setValue(pluginCommand, pluginCommand.getClass().getSuperclass(), true, "activeAliases", aliases.stream().map(String::toLowerCase).collect(Collectors.toList()));
|
||||
Reflection.setValue(pluginCommand, pluginCommand.getClass().getSuperclass(), true, "permission", permission);
|
||||
Reflection.setValue(pluginCommand, pluginCommand.getClass().getSuperclass(), true, "permissionMessage", permissionMessage);
|
||||
commandMap.register(plugin.getName(), pluginCommand);
|
||||
TabooLibAPI.debug("Command " + command + " created. (" + plugin.getName() + ")");
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
TLocale.Logger.error("COMMANDS.INTERNAL.COMMAND-CREATE-FAILED", plugin.getName(), command, e.toString());
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 向服务端注册 BaseMainCommand 类
|
||||
*
|
||||
* @param command 命令全称(需在 plugin.yml 内注册)
|
||||
* @param baseMainCommand 命令对象
|
||||
* @return {@link BaseMainCommand}
|
||||
*/
|
||||
public static BaseMainCommand registerCommand(TCommand tCommand, String command, BaseMainCommand baseMainCommand, Plugin plugin) {
|
||||
if (Bukkit.getPluginCommand(command) == null) {
|
||||
registerPluginCommand(
|
||||
plugin,
|
||||
command,
|
||||
ArrayUtil.skipEmpty(tCommand.description(), "Registered by TabooLib."),
|
||||
ArrayUtil.skipEmpty(tCommand.usage(), "/" + command),
|
||||
ArrayUtil.skipEmpty(ArrayUtil.asList(tCommand.aliases()), new ArrayList<>()),
|
||||
ArrayUtil.skipEmpty(tCommand.permission()),
|
||||
ArrayUtil.skipEmpty(tCommand.permissionMessage()),
|
||||
baseMainCommand,
|
||||
baseMainCommand);
|
||||
}
|
||||
return BaseMainCommand.createCommandExecutor(command, baseMainCommand);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 注册插件的所有 TCommand 命令
|
||||
*/
|
||||
public static void registerCommand(Plugin plugin) {
|
||||
for (Class pluginClass : Files.getClasses(plugin)) {
|
||||
if (BaseMainCommand.class.isAssignableFrom(pluginClass) && pluginClass.isAnnotationPresent(TCommand.class)) {
|
||||
TCommand tCommand = (TCommand) pluginClass.getAnnotation(TCommand.class);
|
||||
try {
|
||||
registerCommand(tCommand, tCommand.name(), (BaseMainCommand) pluginClass.newInstance(), plugin);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// *********************************
|
||||
//
|
||||
// Getter and Setter
|
||||
//
|
||||
// *********************************
|
||||
|
||||
public static SimpleCommandMap getCommandMap() {
|
||||
return commandMap;
|
||||
}
|
||||
|
||||
public static Map<String, Command> getKnownCommands() {
|
||||
return knownCommands;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
package io.izzel.taboolib.module.command.base;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.Lists;
|
||||
import io.izzel.taboolib.TabooLib;
|
||||
import io.izzel.taboolib.TabooLibAPI;
|
||||
import io.izzel.taboolib.Version;
|
||||
import io.izzel.taboolib.locale.TLocale;
|
||||
import io.izzel.taboolib.util.ArrayUtil;
|
||||
import io.izzel.taboolib.util.Strings;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.*;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-05-07 21:38
|
||||
*/
|
||||
public abstract class BaseMainCommand implements CommandExecutor, TabExecutor {
|
||||
|
||||
private PluginCommand registerCommand;
|
||||
private List<Class<?>> linkClasses = new CopyOnWriteArrayList<>();
|
||||
private List<io.izzel.taboolib.module.command.base.BaseSubCommand> subCommands = new CopyOnWriteArrayList<>();
|
||||
|
||||
public static BaseMainCommand createCommandExecutor(String command, BaseMainCommand baseMainCommand) {
|
||||
Preconditions.checkArgument(Bukkit.getPluginCommand(command) != null, "PluginCommand \"" + command + "\" not found");
|
||||
Preconditions.checkArgument(baseMainCommand != null, "Executor cannot be null");
|
||||
Preconditions.checkArgument(baseMainCommand.getClass() != BaseMainCommand.class, "Executor can not be \"BaseMainCommand.class\"");
|
||||
baseMainCommand.setRegisterCommand(Bukkit.getPluginCommand(command));
|
||||
baseMainCommand.getRegisterCommand().setExecutor(baseMainCommand);
|
||||
baseMainCommand.getRegisterCommand().setTabCompleter(baseMainCommand);
|
||||
baseMainCommand.getLinkClasses().add(baseMainCommand.getClass());
|
||||
baseMainCommand.disguisedPlugin();
|
||||
loadCommandRegister(baseMainCommand);
|
||||
return baseMainCommand;
|
||||
}
|
||||
|
||||
public static void loadCommandRegister(BaseMainCommand baseMainCommand) {
|
||||
List<Method> methods = new ArrayList<>();
|
||||
List<CommandField> fields = new ArrayList<>();
|
||||
baseMainCommand.getLinkClasses().forEach(clazz -> java.util.Arrays.stream(clazz.getDeclaredMethods()).filter(method -> method.getAnnotation(CommandRegister.class) != null).forEach(methods::add));
|
||||
if (methods.size() > 0) {
|
||||
methods.sort(Comparator.comparingDouble(a -> a.getAnnotation(CommandRegister.class).priority()));
|
||||
methods.forEach(x -> {
|
||||
try {
|
||||
x.setAccessible(true);
|
||||
x.invoke(baseMainCommand);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
});
|
||||
}
|
||||
baseMainCommand.getLinkClasses().forEach(clazz -> java.util.Arrays.stream(clazz.getDeclaredFields()).filter(field -> field.getAnnotation(CommandRegister.class) != null && field.getType().equals(io.izzel.taboolib.module.command.base.BaseSubCommand.class)).forEach(field -> fields.add(new CommandField(field, clazz))));
|
||||
if (fields.size() > 0) {
|
||||
fields.sort(Comparator.comparingDouble(commandField -> commandField.getField().getAnnotation(CommandRegister.class).priority()));
|
||||
fields.forEach(commandField -> {
|
||||
try {
|
||||
commandField.getField().setAccessible(true);
|
||||
io.izzel.taboolib.module.command.base.BaseSubCommand subCommand = (io.izzel.taboolib.module.command.base.BaseSubCommand) commandField.getField().get(commandField.getParent().newInstance());
|
||||
subCommand.setLabel(commandField.getField().getName());
|
||||
baseMainCommand.registerSubCommand(subCommand);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
});
|
||||
}
|
||||
if (methods.size() + fields.size() > 0) {
|
||||
TabooLibAPI.debug("Registered " + (methods.size() + fields.size()) + " sub-command with " + baseMainCommand.getRegisterCommand().getName() + " (" + baseMainCommand.getRegisterCommand().getPlugin().getName() + ")");
|
||||
}
|
||||
}
|
||||
|
||||
public void setRegisterCommand(PluginCommand registerCommand) {
|
||||
this.registerCommand = registerCommand;
|
||||
}
|
||||
|
||||
public PluginCommand getRegisterCommand() {
|
||||
return registerCommand;
|
||||
}
|
||||
|
||||
public List<Class<?>> getLinkClasses() {
|
||||
return linkClasses;
|
||||
}
|
||||
|
||||
public List<io.izzel.taboolib.module.command.base.BaseSubCommand> getSubCommands() {
|
||||
return subCommands;
|
||||
}
|
||||
|
||||
public void registerSubCommand(io.izzel.taboolib.module.command.base.BaseSubCommand subCommand) {
|
||||
if (subCommand != null) {
|
||||
Preconditions.checkArgument(subCommand.getLabel() != null, "Command label can not be null");
|
||||
Preconditions.checkArgument(subCommand.getArguments() != null, "Command arguments can not be null");
|
||||
}
|
||||
subCommands.add(subCommand);
|
||||
}
|
||||
|
||||
public void onCommandHelp(CommandSender sender, Command command, String label, String[] args) {
|
||||
sender.sendMessage(getEmptyLine());
|
||||
sender.sendMessage(getCommandTitle());
|
||||
sender.sendMessage(getEmptyLine());
|
||||
subCommands.stream().filter(subCommands -> !hideInHelp(subCommands) && hasPermission(sender, subCommands)).map(subCommand -> subCommand == null ? getEmptyLine() : subCommand.getCommandString(label)).forEach(sender::sendMessage);
|
||||
sender.sendMessage(getEmptyLine());
|
||||
}
|
||||
|
||||
abstract public String getCommandTitle();
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(CommandSender commandSender, Command command, String s, String[] args) {
|
||||
if (args.length == 1) {
|
||||
List<String> label = Lists.newArrayList();
|
||||
subCommands.stream().filter(subCommand -> !hideInHelp(subCommand) && hasPermission(commandSender, subCommand)).forEach(l -> {
|
||||
label.add(l.getLabel());
|
||||
label.addAll(Lists.newArrayList(l.getAliases()));
|
||||
});
|
||||
return label.stream().filter(l -> args[0].isEmpty() || l.toLowerCase().startsWith(args[0].toLowerCase())).collect(Collectors.toList());
|
||||
}
|
||||
for (io.izzel.taboolib.module.command.base.BaseSubCommand subCommand : subCommands) {
|
||||
CommandArgument[] arguments = subCommand.getArguments();
|
||||
if (args[0].equalsIgnoreCase(subCommand.getLabel()) && args.length - 1 <= arguments.length) {
|
||||
CommandTab commandTab = arguments[args.length - 2].getTab();
|
||||
if (commandTab != null) {
|
||||
return commandTab.run().stream().filter(l -> args[args.length - 1].isEmpty() || l.toLowerCase().startsWith(args[args.length - 1].toLowerCase())).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (args.length == 0) {
|
||||
onCommandHelp(sender, command, label, args);
|
||||
} else {
|
||||
for (io.izzel.taboolib.module.command.base.BaseSubCommand subCommand : subCommands) {
|
||||
if (subCommand == null || !(args[0].equalsIgnoreCase(subCommand.getLabel()) || java.util.Arrays.stream(subCommand.getAliases()).anyMatch(args[0]::equalsIgnoreCase)) || !hasPermission(sender, subCommand)) {
|
||||
continue;
|
||||
}
|
||||
if (!isConfirmType(sender, subCommand.getType())) {
|
||||
TLocale.sendTo(sender, "COMMANDS.INTERNAL.TYPE-ERROR", args[0], TLocale.asString("COMMANDS.INTERNAL.TYPE-" + subCommand.getType()));
|
||||
return true;
|
||||
}
|
||||
String[] subCommandArgs = ArrayUtil.removeFirst(args);
|
||||
if (subCommand.isParameterConform(subCommandArgs)) {
|
||||
subCommand.onCommand(sender, command, label, subCommand.ignoredLabel() ? subCommandArgs : args);
|
||||
} else {
|
||||
TLocale.sendTo(sender, "COMMANDS.INTERNAL.ERROR-USAGE", args[0], subCommand.getCommandString(label));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
new BukkitRunnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
List<io.izzel.taboolib.module.command.base.BaseSubCommand> commandCompute = subCommands.stream().filter(x -> x != null && hasPermission(sender, x)).sorted((b, a) -> Double.compare(Strings.similarDegree(args[0], a.getLabel()), Strings.similarDegree(args[0], b.getLabel()))).collect(Collectors.toList());
|
||||
if (commandCompute.size() > 0) {
|
||||
TLocale.sendTo(sender, "COMMANDS.INTERNAL.ERROR-COMMAND", args[0], commandCompute.get(0).getCommandString(label).trim());
|
||||
}
|
||||
}
|
||||
}.runTaskAsynchronously(TabooLib.getPlugin());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "registerCommand=" + "BaseMainCommand{" + registerCommand + ", linkClasses=" + linkClasses + ", subCommands=" + subCommands + '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof BaseMainCommand)) {
|
||||
return false;
|
||||
}
|
||||
BaseMainCommand that = (BaseMainCommand) o;
|
||||
return Objects.equals(getLinkClasses(), that.getLinkClasses()) && Objects.equals(getRegisterCommand(), that.getRegisterCommand()) && Objects.equals(getSubCommands(), that.getSubCommands());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getRegisterCommand(), getLinkClasses(), getSubCommands());
|
||||
}
|
||||
|
||||
// *********************************
|
||||
//
|
||||
// Private Methods
|
||||
//
|
||||
// *********************************
|
||||
|
||||
private String getEmptyLine() {
|
||||
return Version.isAfter(Version.v1_8) ? "" : "~";
|
||||
}
|
||||
|
||||
private boolean isConfirmType(CommandSender sender, CommandType commandType) {
|
||||
return commandType == CommandType.ALL
|
||||
|| (sender instanceof Player && commandType == CommandType.PLAYER)
|
||||
|| (sender instanceof ConsoleCommandSender && commandType == CommandType.CONSOLE);
|
||||
}
|
||||
|
||||
private void disguisedPlugin() {
|
||||
linkClasses.forEach(clazz -> disguisedPlugin(clazz, registerCommand.getPlugin()));
|
||||
}
|
||||
|
||||
private void disguisedPlugin(Class<?> targetClass, Plugin plugin) {
|
||||
try {
|
||||
Field pluginField = targetClass.getClassLoader().getClass().getDeclaredField("plugin");
|
||||
pluginField.setAccessible(true);
|
||||
pluginField.set(targetClass.newInstance(), plugin);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hideInHelp(io.izzel.taboolib.module.command.base.BaseSubCommand baseSubCommand) {
|
||||
return baseSubCommand != null && baseSubCommand.hideInHelp();
|
||||
}
|
||||
|
||||
private boolean hasPermission(CommandSender sender, BaseSubCommand baseSubCommand) {
|
||||
return baseSubCommand == null || baseSubCommand.getPermission() == null || sender.hasPermission(baseSubCommand.getPermission());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package io.izzel.taboolib.module.command.base;
|
||||
|
||||
import io.izzel.taboolib.locale.TLocale;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
/**
|
||||
* @author Bkm016
|
||||
* @since 2018-04-17
|
||||
*/
|
||||
public abstract class BaseSubCommand {
|
||||
|
||||
private String label;
|
||||
|
||||
public void setLabel(String label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String[] getAliases() {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
public CommandArgument[] getArguments() {
|
||||
return new CommandArgument[0];
|
||||
}
|
||||
|
||||
public CommandType getType() {
|
||||
return CommandType.ALL;
|
||||
}
|
||||
|
||||
public boolean ignoredLabel() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean requiredPlayer() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getPermission() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean hideInHelp() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isParameterConform(String[] args) {
|
||||
return IntStream.range(0, getArguments().length).noneMatch(i -> getArguments()[i].isRequired() && (args == null || args.length <= i));
|
||||
}
|
||||
|
||||
public String getCommandString(String label) {
|
||||
return TLocale.asString(getDescription() == null ? "COMMANDS.INTERNAL.COMMAND-HELP-EMPTY" : "COMMANDS.INTERNAL.COMMAND-HELP", label, getLabel(), Arrays.stream(getArguments()).map(parameter -> parameter.toString() + " ").collect(Collectors.joining()), getDescription());
|
||||
}
|
||||
|
||||
abstract public void onCommand(CommandSender sender, Command command, String label, String[] args);
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package io.izzel.taboolib.module.command.base;
|
||||
|
||||
import io.izzel.taboolib.locale.TLocale;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author Bkm016
|
||||
* @since 2018-04-17
|
||||
*/
|
||||
public class CommandArgument {
|
||||
|
||||
private String name;
|
||||
private boolean required;
|
||||
private CommandTab tab;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean isRequired() {
|
||||
return required;
|
||||
}
|
||||
|
||||
public CommandTab getTab() {
|
||||
return tab;
|
||||
}
|
||||
|
||||
public CommandArgument(String name) {
|
||||
this(name, true);
|
||||
}
|
||||
|
||||
public CommandArgument(String name, CommandTab tab) {
|
||||
this(name, true, tab);
|
||||
}
|
||||
|
||||
public CommandArgument(String name, boolean required) {
|
||||
this(name, required, null);
|
||||
}
|
||||
|
||||
public CommandArgument(String name, boolean required, CommandTab tab) {
|
||||
this.name = name;
|
||||
this.required = required;
|
||||
this.tab = tab;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return required ? TLocale.asString("COMMANDS.INTERNAL.COMMAND-ARGUMENT-REQUIRE", name) : TLocale.asString("COMMANDS.INTERNAL.COMMAND-ARGUMENT", name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof CommandArgument)) {
|
||||
return false;
|
||||
}
|
||||
CommandArgument that = (CommandArgument) o;
|
||||
return isRequired() == that.isRequired() &&
|
||||
Objects.equals(getName(), that.getName()) &&
|
||||
Objects.equals(tab, that.tab);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getName(), isRequired(), tab);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package io.izzel.taboolib.module.command.base;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-05-23 3:07
|
||||
*/
|
||||
public class CommandField {
|
||||
|
||||
private final Field field;
|
||||
private final Class<?> parent;
|
||||
|
||||
public CommandField(Field field, Class<?> parent) {
|
||||
this.field = field;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public Field getField() {
|
||||
return field;
|
||||
}
|
||||
|
||||
public Class<?> getParent() {
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package io.izzel.taboolib.module.command.base;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-05-09 22:38
|
||||
*/
|
||||
@Target({ElementType.METHOD, ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface CommandRegister {
|
||||
|
||||
double priority() default 0;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package io.izzel.taboolib.module.command.base;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 为了防止与 TabExecutor 混淆所以名称改为 CompleterTab
|
||||
*
|
||||
* @author sky
|
||||
*/
|
||||
public interface CommandTab {
|
||||
|
||||
List<String> run();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package io.izzel.taboolib.module.command.base;
|
||||
|
||||
/**
|
||||
* @author Bkm016
|
||||
* @since 2018-04-17
|
||||
*/
|
||||
public enum CommandType {
|
||||
|
||||
CONSOLE, PLAYER, ALL
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package io.izzel.taboolib.module.command.lite;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
/**
|
||||
* 为了防止与 CommandExecutor 混淆所以名称改为 CompleterCommand
|
||||
*
|
||||
* @author sky
|
||||
*/
|
||||
public interface CompleterCommand {
|
||||
|
||||
void execute(CommandSender sender, String[] args);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package io.izzel.taboolib.module.command.lite;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 为了防止与 TabExecutor 混淆所以名称改为 CompleterTab
|
||||
*
|
||||
* @author sky
|
||||
*/
|
||||
public interface CompleterTab {
|
||||
|
||||
List<String> execute(CommandSender sender, String[] args);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
package io.izzel.taboolib.module.command.lite;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import io.izzel.taboolib.module.command.TCommandHandler;
|
||||
import io.izzel.taboolib.util.ArrayUtil;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-08-27 8:42
|
||||
* @BuilderLevel 1.0
|
||||
*/
|
||||
public class SimpleCommandBuilder {
|
||||
|
||||
public static final CompleterTab EMPTY_COMPLETER_TAB = ((sender, args) -> new ArrayList<>());
|
||||
public static final CompleterCommand EMPTY_COMPLETER_COMMAND = ((sender, args) -> {});
|
||||
|
||||
private String command;
|
||||
private Plugin plugin;
|
||||
private String description;
|
||||
private String usage;
|
||||
private List<String> aliases;
|
||||
private String permission;
|
||||
private String permissionMessage;
|
||||
private CompleterTab completerTab = EMPTY_COMPLETER_TAB;
|
||||
private CompleterCommand completerCommand = EMPTY_COMPLETER_COMMAND;
|
||||
private boolean forceRegister;
|
||||
private boolean build;
|
||||
|
||||
SimpleCommandBuilder(String command, Plugin plugin) {
|
||||
this.command = command;
|
||||
this.plugin = plugin;
|
||||
this.description = "";
|
||||
this.usage = "/" + command;
|
||||
this.aliases = new ArrayList<>();
|
||||
this.build = false;
|
||||
}
|
||||
|
||||
public static SimpleCommandBuilder create(String command, Plugin plugin) {
|
||||
return new SimpleCommandBuilder(command.toLowerCase(), plugin);
|
||||
}
|
||||
|
||||
public SimpleCommandBuilder command(String command) {
|
||||
this.command = command;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimpleCommandBuilder plugin(Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimpleCommandBuilder description(String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimpleCommandBuilder usage(String usage) {
|
||||
this.usage = usage;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimpleCommandBuilder aliases(String... aliases) {
|
||||
this.aliases = ArrayUtil.asList(aliases);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimpleCommandBuilder permission(String permission) {
|
||||
this.permission = permission;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimpleCommandBuilder permissionMessage(String permissionMessage) {
|
||||
this.permissionMessage = permissionMessage;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimpleCommandBuilder execute(CompleterCommand completerCommand) {
|
||||
this.completerCommand = completerCommand;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimpleCommandBuilder tab(CompleterTab completerTab) {
|
||||
this.completerTab = completerTab;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimpleCommandBuilder forceRegister() {
|
||||
this.forceRegister = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimpleCommandBuilder build() {
|
||||
Preconditions.checkNotNull(plugin, "缺少 \"plugin\" 部分");
|
||||
Preconditions.checkNotNull(command, "缺少 \"command\" 部分");
|
||||
Preconditions.checkNotNull(completerCommand, "缺少 \"CompleterCommand\" 部分");
|
||||
Preconditions.checkNotNull(completerTab, "缺少 \"CompleterTab\" 部分");
|
||||
if (forceRegister) {
|
||||
TCommandHandler.getKnownCommands().remove(command);
|
||||
}
|
||||
TCommandHandler.registerPluginCommand(
|
||||
plugin,
|
||||
command,
|
||||
description,
|
||||
usage,
|
||||
aliases,
|
||||
permission,
|
||||
permissionMessage,
|
||||
(sender, command, s, args) -> {
|
||||
completerCommand.execute(sender, args);
|
||||
return true;
|
||||
},
|
||||
(sender, command, s, args) -> {
|
||||
try {
|
||||
return completerTab.execute(sender, args);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
});
|
||||
build = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
// *********************************
|
||||
//
|
||||
// Getter and Setter
|
||||
//
|
||||
// *********************************
|
||||
|
||||
public String getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
public Plugin getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public String getUsage() {
|
||||
return usage;
|
||||
}
|
||||
|
||||
public List<String> getAliases() {
|
||||
return aliases;
|
||||
}
|
||||
|
||||
public String getPermission() {
|
||||
return permission;
|
||||
}
|
||||
|
||||
public String getPermissionMessage() {
|
||||
return permissionMessage;
|
||||
}
|
||||
|
||||
public CompleterTab getCompleterTab() {
|
||||
return completerTab;
|
||||
}
|
||||
|
||||
public CompleterCommand getCompleterCommand() {
|
||||
return completerCommand;
|
||||
}
|
||||
|
||||
public boolean isForceRegister() {
|
||||
return forceRegister;
|
||||
}
|
||||
|
||||
public boolean isBuild() {
|
||||
return build;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package io.izzel.taboolib.module.compat;
|
||||
|
||||
import io.izzel.taboolib.module.inject.TFunction;
|
||||
import net.milkbowl.vault.economy.Economy;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||
|
||||
/**
|
||||
* @Author 坏黑
|
||||
* @Since 2019-07-05 18:50
|
||||
*/
|
||||
@TFunction(enable = "init")
|
||||
public class EconomyHook {
|
||||
|
||||
private static Economy economy;
|
||||
|
||||
static void init() {
|
||||
if (Bukkit.getPluginManager().getPlugin("Vault") == null) {
|
||||
return;
|
||||
}
|
||||
RegisteredServiceProvider<Economy> l = Bukkit.getServer().getServicesManager().getRegistration(Economy.class);
|
||||
if (l != null) {
|
||||
economy = l.getProvider();
|
||||
}
|
||||
}
|
||||
|
||||
public static void remove(OfflinePlayer p, double d) {
|
||||
economy.withdrawPlayer(p, d);
|
||||
}
|
||||
|
||||
public static void add(OfflinePlayer p, double d) {
|
||||
economy.depositPlayer(p, d);
|
||||
}
|
||||
|
||||
public static void set(OfflinePlayer p, double d) {
|
||||
add(p, d - get(p));
|
||||
}
|
||||
|
||||
public static double get(OfflinePlayer p) {
|
||||
return economy.getBalance(p);
|
||||
}
|
||||
|
||||
public static void create(OfflinePlayer p) {
|
||||
economy.createPlayerAccount(p);
|
||||
}
|
||||
|
||||
public static boolean exists() {
|
||||
return economy != null;
|
||||
}
|
||||
|
||||
public static net.milkbowl.vault.economy.Economy getEconomy() {
|
||||
return economy;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package io.izzel.taboolib.module.compat;
|
||||
|
||||
import io.izzel.taboolib.module.inject.TFunction;
|
||||
import net.milkbowl.vault.permission.Permission;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@TFunction(enable = "init")
|
||||
public class PermissionHook {
|
||||
|
||||
private static Permission perms;
|
||||
|
||||
static void init() {
|
||||
if (Bukkit.getPluginManager().getPlugin("Vault") == null) {
|
||||
return;
|
||||
}
|
||||
RegisteredServiceProvider<Permission> rsp = Bukkit.getServer().getServicesManager().getRegistration(Permission.class);
|
||||
perms = rsp.getProvider();
|
||||
}
|
||||
|
||||
public static Permission getPermission() {
|
||||
return perms;
|
||||
}
|
||||
|
||||
public static void addPermission(Player player, String perm) {
|
||||
perms.playerAdd(player, perm);
|
||||
}
|
||||
|
||||
public static void removePermission(Player player, String perm) {
|
||||
perms.playerRemove(player, perm);
|
||||
}
|
||||
|
||||
public static boolean hasPermission(Player player, String perm) {
|
||||
return perms.playerHas(player, perm) || Arrays.stream(perms.getPlayerGroups(player)).anyMatch(group -> perms.groupHas(player.getWorld(), group, perm));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package io.izzel.taboolib.module.compat;
|
||||
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import io.izzel.taboolib.module.inject.TFunction;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@TFunction(enable = "init")
|
||||
public abstract class PlaceholderHook {
|
||||
|
||||
private static PlaceholderHook impl;
|
||||
|
||||
static void init() {
|
||||
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
|
||||
impl = new PlaceholderImpl();
|
||||
} else {
|
||||
impl = new AbstractImpl();
|
||||
}
|
||||
}
|
||||
|
||||
public static String replace(CommandSender sender, String text) {
|
||||
return sender instanceof Player ? impl.replace(((Player) sender), text) : text;
|
||||
}
|
||||
|
||||
abstract String replace(Player player, String text);
|
||||
|
||||
private static class PlaceholderImpl extends PlaceholderHook {
|
||||
|
||||
@Override
|
||||
String replace(Player player, String text) {
|
||||
return PlaceholderAPI.setPlaceholders(player, text);
|
||||
}
|
||||
}
|
||||
|
||||
private static class AbstractImpl extends PlaceholderHook {
|
||||
|
||||
@Override
|
||||
String replace(Player player, String text) {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package io.izzel.taboolib.module.compat;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldguard.WorldGuard;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.protection.managers.RegionManager;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @Author AgarthaLib
|
||||
*/
|
||||
public class WorldGuardHook {
|
||||
|
||||
public static final WorldGuardHook INSTANCE = new WorldGuardHook();
|
||||
private WorldGuardPlugin worldGuard;
|
||||
private Method getRegionManager;
|
||||
|
||||
public WorldGuardHook() {
|
||||
Preconditions.checkNotNull(Bukkit.getServer().getPluginManager().getPlugin("WorldGuard"), "WorldGuard was not found.");
|
||||
worldGuard = WorldGuardPlugin.inst();
|
||||
if (!worldGuard.getDescription().getVersion().startsWith("7")) {
|
||||
try {
|
||||
getRegionManager = WorldGuardPlugin.class.getDeclaredMethod("getRegionManager", World.class);
|
||||
getRegionManager.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public WorldGuardPlugin getWorldGuard() {
|
||||
return this.worldGuard;
|
||||
}
|
||||
|
||||
public RegionManager getRegionManager(World world) {
|
||||
if (worldGuard.getDescription().getVersion().startsWith("7")) {
|
||||
return WorldGuard.getInstance().getPlatform().getRegionContainer().get(BukkitAdapter.adapt(world));
|
||||
} else {
|
||||
try {
|
||||
return (RegionManager) getRegionManager.invoke(worldGuard, world);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isRegionManagerExists(World world) {
|
||||
return this.getRegionManager(world) != null;
|
||||
}
|
||||
|
||||
public Collection<String> getRegionIDs(World world) {
|
||||
return getRegionManager(world).getRegions().keySet();
|
||||
}
|
||||
|
||||
public Collection<ProtectedRegion> getRegions(World world) {
|
||||
return getRegionManager(world).getRegions().values();
|
||||
}
|
||||
|
||||
public List<String> getRegionsAtLocation(World world, Location location) {
|
||||
return getRegions(world).stream().filter(protectedRegion -> protectedRegion.contains(location.getBlockX(), location.getBlockY(), location.getBlockZ())).map(ProtectedRegion::getId).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public ProtectedRegion getRegion(World world, String id) {
|
||||
RegionManager regionManager = this.getRegionManager(world);
|
||||
return regionManager != null ? regionManager.getRegions().keySet().stream().filter(key -> key.equalsIgnoreCase(id)).findFirst().map(regionManager::getRegion).orElse(null) : null;
|
||||
}
|
||||
|
||||
public boolean isRegionExists(World world, String id) {
|
||||
return this.getRegion(world, id) != null;
|
||||
}
|
||||
|
||||
public boolean isPlayerInsideRegion(ProtectedRegion region, Player player) {
|
||||
Location location = player.getLocation();
|
||||
return region.contains(location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
||||
}
|
||||
}
|
||||
106
src/main/scala/io/izzel/taboolib/module/config/TConfig.java
Normal file
106
src/main/scala/io/izzel/taboolib/module/config/TConfig.java
Normal file
@@ -0,0 +1,106 @@
|
||||
package io.izzel.taboolib.module.config;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import io.izzel.taboolib.TabooLib;
|
||||
import io.izzel.taboolib.TabooLibAPI;
|
||||
import io.izzel.taboolib.locale.TLocale;
|
||||
import io.izzel.taboolib.module.logger.TLogger;
|
||||
import io.izzel.taboolib.util.Files;
|
||||
import io.izzel.taboolib.util.Ref;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-09-08 15:00
|
||||
*/
|
||||
public class TConfig extends YamlConfiguration {
|
||||
|
||||
private static Map<String, List<File>> files = Maps.newHashMap();
|
||||
private File file;
|
||||
private Runnable runnable;
|
||||
|
||||
private TConfig(File file, Plugin plugin) {
|
||||
files.computeIfAbsent(plugin.getName(), name -> new ArrayList<>()).add(file);
|
||||
this.file = file;
|
||||
reload();
|
||||
TConfigWatcher.getInst().addSimpleListener(this.file, this::reload);
|
||||
TabooLibAPI.debug("Loaded TConfiguration \"" + file.getName() + "\" from Plugin \"" + plugin.getName() + "\"");
|
||||
}
|
||||
|
||||
public static Map<String, List<File>> getFiles() {
|
||||
return files;
|
||||
}
|
||||
|
||||
public static TConfig create(File file) {
|
||||
return new TConfig(file, Ref.getCallerPlugin(Ref.getCallerClass(3).orElse(TabooLib.class)));
|
||||
}
|
||||
|
||||
public static TConfig create(File file, Plugin plugin) {
|
||||
return new TConfig(file, plugin);
|
||||
}
|
||||
|
||||
public static TConfig create(Plugin plugin, String path) {
|
||||
File file = new File(plugin.getDataFolder(), path);
|
||||
if (!file.exists()) {
|
||||
Files.releaseResource(plugin, path, false);
|
||||
}
|
||||
return create(file, plugin);
|
||||
}
|
||||
|
||||
public String getStringColored(String path) {
|
||||
return TLocale.Translate.setColored(getString(path));
|
||||
}
|
||||
|
||||
public String getStringColored(String path, String def) {
|
||||
return TLocale.Translate.setColored(getString(path, def));
|
||||
}
|
||||
|
||||
public List<String> getStringListColored(String path) {
|
||||
return TLocale.Translate.setColored(getStringList(path));
|
||||
}
|
||||
|
||||
public void release() {
|
||||
TConfigWatcher.getInst().removeListener(file);
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
try {
|
||||
load(file);
|
||||
runListener();
|
||||
} catch (IOException | InvalidConfigurationException e) {
|
||||
TLogger.getGlobalLogger().warn("Cannot load configuration from stream: " + e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// *********************************
|
||||
//
|
||||
// Getter and Setter
|
||||
//
|
||||
// *********************************
|
||||
|
||||
public File getFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
public TConfig listener(Runnable runnable) {
|
||||
this.runnable = runnable;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void runListener() {
|
||||
try {
|
||||
Optional.ofNullable(runnable).ifPresent(Runnable::run);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package io.izzel.taboolib.module.config;
|
||||
|
||||
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
|
||||
import org.apache.commons.lang3.tuple.Triple;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author lzzelAliz
|
||||
*/
|
||||
public class TConfigWatcher {
|
||||
|
||||
private static TConfigWatcher configWatcher = new TConfigWatcher();
|
||||
private final ScheduledExecutorService service = Executors.newScheduledThreadPool(1, new BasicThreadFactory.Builder().namingPattern("TConfigWatcherService-%d").build());
|
||||
private final Map<WatchService, Triple<File, Object, Consumer<Object>>> map = new HashMap<>();
|
||||
|
||||
public TConfigWatcher() {
|
||||
service.scheduleAtFixedRate(() -> {
|
||||
synchronized (map) {
|
||||
map.forEach((service, triple) -> {
|
||||
WatchKey key;
|
||||
while ((key = service.poll()) != null) {
|
||||
for (WatchEvent<?> watchEvent : key.pollEvents()) {
|
||||
if (triple.getLeft().getName().equals(Objects.toString(watchEvent.context()))) {
|
||||
triple.getRight().accept(triple.getMiddle());
|
||||
}
|
||||
}
|
||||
key.reset();
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 1000, 100, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
public static TConfigWatcher getInst() {
|
||||
return configWatcher;
|
||||
}
|
||||
|
||||
public void addSimpleListener(File file, Runnable runnable) {
|
||||
addListener(file, null, obj -> runnable.run());
|
||||
}
|
||||
|
||||
public void addOnListen(File file, Object obj, Consumer<Object> consumer) {
|
||||
try {
|
||||
WatchService service = FileSystems.getDefault().newWatchService();
|
||||
file.getParentFile().toPath().register(service, StandardWatchEventKinds.ENTRY_MODIFY);
|
||||
map.putIfAbsent(service, Triple.of(file, obj, consumer));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> void addListener(File file, T obj, Consumer<T> consumer) {
|
||||
addOnListen(file, obj, (Consumer<Object>) consumer);
|
||||
}
|
||||
|
||||
public void removeListener(File file) {
|
||||
synchronized (map) {
|
||||
map.entrySet().removeIf(entry -> {
|
||||
if (entry.getValue().getLeft().equals(file)) {
|
||||
try {
|
||||
entry.getKey().close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterAll() {
|
||||
service.shutdown();
|
||||
map.forEach((service, pair) -> {
|
||||
try {
|
||||
service.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package io.izzel.taboolib.module.dependency;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Dependencies {
|
||||
|
||||
Dependency[] value();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package io.izzel.taboolib.module.dependency;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Repeatable(Dependencies.class)
|
||||
public @interface Dependency {
|
||||
|
||||
enum Type {PLUGIN, LIBRARY}
|
||||
|
||||
Type type();
|
||||
|
||||
String plugin() default "";
|
||||
|
||||
String maven() default "";
|
||||
|
||||
String mavenRepo() default TDependency.MAVEN_REPO;
|
||||
|
||||
String url() default "";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package io.izzel.taboolib.module.dependency;
|
||||
|
||||
import io.izzel.taboolib.TabooLib;
|
||||
import io.izzel.taboolib.util.Files;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class TDependency {
|
||||
|
||||
// 阿里 http://maven.aliyun.com/nexus/content/groups/public
|
||||
public static final String MAVEN_REPO = "http://repo1.maven.org/maven2";
|
||||
|
||||
/**
|
||||
* 请求一个插件作为依赖,这个插件将会在所有已经添加的 Jenkins 仓库、Maven 仓库寻找
|
||||
* <p>
|
||||
* 阻塞线程进行下载/加载
|
||||
*
|
||||
* @param args 插件名称,下载地址(可选)
|
||||
* @return 是否成功加载了依赖
|
||||
*/
|
||||
public static boolean requestPlugin(String... args) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求一个库作为依赖,这个库将会在 Maven Central、oss.sonatype 以及自定义的 Maven 仓库寻找
|
||||
* <p>
|
||||
* 阻塞线程进行下载/加载
|
||||
*
|
||||
* @param type 依赖名,格式为 groupId:artifactId:version
|
||||
* @return 是否成功加载库,如果加载成功,插件将可以任意调用使用的类
|
||||
*/
|
||||
public static boolean requestLib(String type, String repo, String url) {
|
||||
// 清理大小为 0 的依赖文件
|
||||
File libFolder = new File(TabooLib.getPlugin().getDataFolder(), "/libs");
|
||||
if (libFolder.exists()) {
|
||||
Arrays.stream(libFolder.listFiles()).filter(listFile -> listFile.length() == 0).forEach(File::delete);
|
||||
}
|
||||
if (type.matches(".*:.*:.*")) {
|
||||
String[] arr = type.split(":");
|
||||
File file = new File(TabooLib.getPlugin().getDataFolder(), "/libs/" + String.join("-", arr) + ".jar");
|
||||
if (file.exists()) {
|
||||
TDependencyLoader.addToPath(TabooLib.getPlugin(), file);
|
||||
return true;
|
||||
} else {
|
||||
if (downloadMaven(repo, arr[0], arr[1], arr[2], file, url)) {
|
||||
TDependencyLoader.addToPath(TabooLib.getPlugin(), file);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean downloadMaven(String url, String groupId, String artifactId, String version, File target, String dl) {
|
||||
Files.toFile(Files.readFromURL(dl.length() == 0 ? url + "/" + groupId.replace('.', '/') + "/" + artifactId + "/" + version + "/" + artifactId + "-" + version + ".jar" : dl, ""), Files.file(target));
|
||||
return target.length() > 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package io.izzel.taboolib.module.dependency;
|
||||
|
||||
import io.izzel.taboolib.TabooLibAPI;
|
||||
import io.izzel.taboolib.locale.TLocale;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* @author Izzel_Aliz
|
||||
*/
|
||||
public class TDependencyInjector {
|
||||
|
||||
public static Dependency[] getDependencies(Class<?> clazz) {
|
||||
Dependency[] dependencies = new Dependency[0];
|
||||
Dependencies d = clazz.getAnnotation(Dependencies.class);
|
||||
if (d != null) {
|
||||
dependencies = d.value();
|
||||
}
|
||||
Dependency d2 = clazz.getAnnotation(Dependency.class);
|
||||
if (d2 != null) {
|
||||
dependencies = new Dependency[] {d2};
|
||||
}
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
public static void inject(Plugin plugin, Class<?> clazz) {
|
||||
inject(plugin.getName(), clazz);
|
||||
}
|
||||
|
||||
public static void inject(String name, Class<?> clazz) {
|
||||
for (Dependency dependency : getDependencies(clazz)) {
|
||||
if (dependency.type() == Dependency.Type.LIBRARY) {
|
||||
if (TDependency.requestLib(dependency.maven(), dependency.mavenRepo(), dependency.url())) {
|
||||
TabooLibAPI.debug(" Loaded " + String.join(":", dependency.maven()) + " (" + name + ")");
|
||||
} else {
|
||||
TLocale.Logger.warn("DEPENDENCY.LIBRARY-LOAD-FAIL", name, String.join(":", dependency.maven()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package io.izzel.taboolib.module.inject;
|
||||
|
||||
/**
|
||||
* @author sky
|
||||
*/
|
||||
public class Container {
|
||||
|
||||
private final Object container;
|
||||
private final boolean uniqueId;
|
||||
|
||||
public Container(Object container, boolean uniqueId) {
|
||||
this.container = container;
|
||||
this.uniqueId = uniqueId;
|
||||
}
|
||||
|
||||
public Object getContainer() {
|
||||
return container;
|
||||
}
|
||||
|
||||
public boolean isUniqueId() {
|
||||
return uniqueId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package io.izzel.taboolib.module.inject;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-09-14 23:45
|
||||
*/
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface PlayerContainer {
|
||||
|
||||
boolean uniqueId() default false;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package io.izzel.taboolib.module.inject;
|
||||
|
||||
import io.izzel.taboolib.TabooLibLoader;
|
||||
import io.izzel.taboolib.module.logger.TLogger;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-09-14 23:45
|
||||
*/
|
||||
@TListener
|
||||
public class PlayerContainerLoader implements Listener, TabooLibLoader.Loader {
|
||||
|
||||
static Map<String, List<Container>> pluginContainer = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void postLoad(Plugin plugin, Class<?> pluginClass) {
|
||||
for (Field field : pluginClass.getDeclaredFields()) {
|
||||
PlayerContainer annotation = field.getAnnotation(PlayerContainer.class);
|
||||
if (annotation == null) {
|
||||
continue;
|
||||
}
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
pluginContainer.computeIfAbsent(plugin.getName(), name -> new ArrayList<>()).add(new Container(field.get(pluginClass), annotation.uniqueId()));
|
||||
} catch (IllegalAccessException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unload(Plugin plugin, Class<?> cancelClass) {
|
||||
pluginContainer.remove(plugin.getName());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onQuit(PlayerQuitEvent e) {
|
||||
pluginContainer.values().stream().flatMap(Collection::stream).forEach(container -> {
|
||||
if (container.getContainer() instanceof Map) {
|
||||
((Map) container.getContainer()).remove(container.isUniqueId() ? e.getPlayer().getUniqueId() : e.getPlayer().getName());
|
||||
} else if (container.getContainer() instanceof Collection) {
|
||||
((Collection) container.getContainer()).remove(container.isUniqueId() ? e.getPlayer().getUniqueId() : e.getPlayer().getName());
|
||||
} else {
|
||||
TLogger.getGlobalLogger().error("Invalid Container: " + container.getContainer().getClass().getSimpleName());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package io.izzel.taboolib.module.inject;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-09-08 14:01
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface TFunction {
|
||||
|
||||
String enable() default "onEnable";
|
||||
String disable() default "onDisable";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package io.izzel.taboolib.module.inject;
|
||||
|
||||
import io.izzel.taboolib.TabooLibAPI;
|
||||
import io.izzel.taboolib.TabooLibLoader;
|
||||
import io.izzel.taboolib.module.logger.TLogger;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-09-08 14:00
|
||||
*/
|
||||
public class TFunctionLoader implements TabooLibLoader.Loader {
|
||||
|
||||
@Override
|
||||
public void postLoad(Plugin plugin, Class<?> pluginClass) {
|
||||
if (pluginClass.isAnnotationPresent(TFunction.class)) {
|
||||
TFunction function = pluginClass.getAnnotation(TFunction.class);
|
||||
try {
|
||||
Method method = pluginClass.getDeclaredMethod(function.enable());
|
||||
if (!Modifier.isStatic(method.getModifiers())) {
|
||||
TLogger.getGlobalLogger().error(method.getName() + " is not a static method.");
|
||||
return;
|
||||
}
|
||||
method.setAccessible(true);
|
||||
method.invoke(null);
|
||||
TabooLibAPI.debug("Function " + pluginClass.getSimpleName() + " loaded. (" + plugin.getName() + ")");
|
||||
} catch (NoSuchMethodException ignore) {
|
||||
} catch (Exception e) {
|
||||
TLogger.getGlobalLogger().warn("TFunction load Failed: " + pluginClass.getName());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unload(Plugin plugin, Class<?> pluginClass) {
|
||||
if (pluginClass.isAnnotationPresent(TFunction.class)) {
|
||||
TFunction function = pluginClass.getAnnotation(TFunction.class);
|
||||
try {
|
||||
Method method = pluginClass.getDeclaredMethod(function.disable());
|
||||
if (!Modifier.isStatic(method.getModifiers())) {
|
||||
TLogger.getGlobalLogger().error(method.getName() + " is not a static method.");
|
||||
return;
|
||||
}
|
||||
method.setAccessible(true);
|
||||
method.invoke(null);
|
||||
TabooLibAPI.debug("Function " + pluginClass.getSimpleName() + " unloaded. (" + plugin.getName() + ")");
|
||||
} catch (NoSuchMethodException ignore) {
|
||||
} catch (Exception e) {
|
||||
TLogger.getGlobalLogger().warn("TFunction unload Failed: " + pluginClass.getName());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
18
src/main/scala/io/izzel/taboolib/module/inject/TInject.java
Normal file
18
src/main/scala/io/izzel/taboolib/module/inject/TInject.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package io.izzel.taboolib.module.inject;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-10-05 12:11
|
||||
*/
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface TInject {
|
||||
|
||||
String[] value() default {};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
package io.izzel.taboolib.module.inject;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import io.izzel.taboolib.TabooLibAPI;
|
||||
import io.izzel.taboolib.TabooLibLoader;
|
||||
import io.izzel.taboolib.module.command.lite.SimpleCommandBuilder;
|
||||
import io.izzel.taboolib.module.config.TConfig;
|
||||
import io.izzel.taboolib.module.logger.TLogger;
|
||||
import io.izzel.taboolib.module.packet.TPacketHandler;
|
||||
import io.izzel.taboolib.module.packet.TPacketListener;
|
||||
import io.izzel.taboolib.origin.lite.cooldown.Cooldown;
|
||||
import io.izzel.taboolib.origin.lite.cooldown.Cooldowns;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-10-05 13:40
|
||||
*/
|
||||
public class TInjectLoader implements TabooLibLoader.Loader {
|
||||
|
||||
private static Map<Class<?>, TInjectTask> injectTypes = Maps.newLinkedHashMap();
|
||||
|
||||
static {
|
||||
// Instance Inject
|
||||
injectTypes.put(Plugin.class, (plugin, field, args, instance) -> {
|
||||
try {
|
||||
field.set(instance, plugin);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
// TLogger Inject
|
||||
injectTypes.put(TLogger.class, (plugin, field, args, instance) -> {
|
||||
try {
|
||||
field.set(instance, args.length == 0 ? TLogger.getUnformatted(plugin) : TLogger.getUnformatted(args[0]));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
// TPacketListener Inject
|
||||
injectTypes.put(TPacketListener.class, (plugin, field, args, instance) -> {
|
||||
try {
|
||||
TPacketHandler.addListener(plugin, ((TPacketListener) field.get(instance)));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
// TConfiguration Inject
|
||||
injectTypes.put(TConfig.class, (plugin, field, args, instance) -> {
|
||||
try {
|
||||
field.set(instance, TConfig.create(plugin, args.length == 0 ? "config.yml" : args[0]));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
// SimpleCommandBuilder Inject
|
||||
injectTypes.put(SimpleCommandBuilder.class, (plugin, field, args, instance) -> {
|
||||
try {
|
||||
SimpleCommandBuilder builder = (SimpleCommandBuilder) field.get(instance);
|
||||
if (builder.isBuild()) {
|
||||
TLogger.getGlobalLogger().error("Command was registered. (" + field.getType().getName() + ")");
|
||||
} else {
|
||||
if (builder.getPlugin() == null) {
|
||||
builder.plugin(plugin);
|
||||
}
|
||||
builder.build();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
// CooldownPack Inject
|
||||
injectTypes.put(Cooldown.class, (plugin, field, args, instance) -> {
|
||||
try {
|
||||
Cooldowns.register((Cooldown) field.get(instance), plugin);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int priority() {
|
||||
return -999;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preLoad(Plugin plugin, Class<?> pluginClass) {
|
||||
for (Field declaredField : pluginClass.getDeclaredFields()) {
|
||||
TInject annotation = declaredField.getAnnotation(TInject.class);
|
||||
// 是否为主类类型
|
||||
if (annotation == null || !declaredField.getType().equals(plugin.getClass())) {
|
||||
continue;
|
||||
}
|
||||
Object instance = null;
|
||||
// 如果是非静态类型
|
||||
if (!Modifier.isStatic(declaredField.getModifiers())) {
|
||||
// 是否为主类
|
||||
if (pluginClass.equals(plugin.getClass())) {
|
||||
instance = plugin;
|
||||
} else {
|
||||
TLogger.getGlobalLogger().error(declaredField.getName() + " is not a static field. (" + declaredField.getType().getName() + ")");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
inject(plugin, declaredField, instance, annotation, injectTypes.get(Plugin.class));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postLoad(Plugin plugin, Class<?> pluginClass) {
|
||||
for (Field declaredField : pluginClass.getDeclaredFields()) {
|
||||
TInject annotation = declaredField.getAnnotation(TInject.class);
|
||||
if (annotation == null || declaredField.getType().equals(plugin.getClass())) {
|
||||
continue;
|
||||
}
|
||||
Object instance = null;
|
||||
// 如果是非静态类型
|
||||
if (!Modifier.isStatic(declaredField.getModifiers())) {
|
||||
// 是否为主类
|
||||
if (pluginClass.equals(plugin.getClass())) {
|
||||
instance = plugin;
|
||||
} else {
|
||||
TLogger.getGlobalLogger().error(declaredField.getName() + " is not a static field. (" + declaredField.getType().getName() + ")");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
TInjectTask tInjectTask = injectTypes.get(declaredField.getType());
|
||||
if (tInjectTask != null) {
|
||||
inject(plugin, declaredField, instance, annotation, tInjectTask);
|
||||
} else {
|
||||
TLogger.getGlobalLogger().error(declaredField.getName() + " is an invalid inject type. (" + declaredField.getType().getName() + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void inject(Plugin plugin, Field field, Object instance, TInject annotation, TInjectTask injectTask) {
|
||||
try {
|
||||
field.setAccessible(true);
|
||||
injectTask.run(plugin, field, annotation.value(), instance);
|
||||
TabooLibAPI.debug(field.getName() + " injected. (" + field.getType().getName() + ")");
|
||||
} catch (Throwable e) {
|
||||
TLogger.getGlobalLogger().error(field.getName() + " inject failed: " + e.getMessage() + " (" + field.getType().getName() + ")");
|
||||
if (e.getMessage() == null) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package io.izzel.taboolib.module.inject;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-10-05 13:41
|
||||
*/
|
||||
public interface TInjectTask {
|
||||
|
||||
void run(Plugin plugin, Field field, String[] args, Object instance);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package io.izzel.taboolib.module.inject;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-08-22 13:41
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface TListener {
|
||||
|
||||
/**
|
||||
* 注册时执行的方法名
|
||||
*/
|
||||
String register() default "";
|
||||
|
||||
/**
|
||||
* 注销时执行的方法名
|
||||
*/
|
||||
String cancel() default "";
|
||||
|
||||
/**
|
||||
* 注册时判断的方法名,需返回布尔值
|
||||
*/
|
||||
String condition() default "";
|
||||
|
||||
/**
|
||||
* 注册前判断依赖插件
|
||||
*/
|
||||
String[] depend() default "";
|
||||
|
||||
/**
|
||||
* 注册前判断依赖版本
|
||||
*/
|
||||
String version() default ">0";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
package io.izzel.taboolib.module.inject;
|
||||
|
||||
import io.izzel.taboolib.TabooLibAPI;
|
||||
import io.izzel.taboolib.TabooLibLoader;
|
||||
import io.izzel.taboolib.Version;
|
||||
import io.izzel.taboolib.module.logger.TLogger;
|
||||
import io.izzel.taboolib.origin.cronus.util.StringExpression;
|
||||
import io.izzel.taboolib.util.Strings;
|
||||
import io.izzel.taboolib.util.Reflection;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-08-22 13:48
|
||||
*/
|
||||
public class TListenerHandler {
|
||||
|
||||
private static HashMap<String, List<Listener>> listeners = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 初始化所有插件的所有监听器
|
||||
*/
|
||||
public static void setupListeners() {
|
||||
for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
|
||||
try {
|
||||
setupListener(plugin);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化插件的所有监听器
|
||||
* 该操作会执行无参构造方法
|
||||
*
|
||||
* @param plugin 插件
|
||||
*/
|
||||
public static void setupListener(Plugin plugin) {
|
||||
for (Class<?> pluginClass : TabooLibLoader.getPluginClassSafely(plugin)) {
|
||||
if (Listener.class.isAssignableFrom(pluginClass) && pluginClass.isAnnotationPresent(TListener.class)) {
|
||||
try {
|
||||
TListener tListener = pluginClass.getAnnotation(TListener.class);
|
||||
// 检查版本
|
||||
if (!new StringExpression(tListener.version()).isSelect(Version.getCurrentVersion().getVersionInt())) {
|
||||
continue;
|
||||
}
|
||||
// 检查注册条件
|
||||
if (tListener.depend().length > 0 && !Strings.isBlank(tListener.depend()[0])) {
|
||||
if (Arrays.stream(tListener.depend()).anyMatch(depend -> Bukkit.getPluginManager().getPlugin(depend) == null)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// 实例化监听器
|
||||
Listener listener = plugin.getClass().equals(pluginClass) ? (Listener) plugin : (Listener) Reflection.instantiateObject(pluginClass);
|
||||
try {
|
||||
listeners.computeIfAbsent(plugin.getName(), name -> new ArrayList<>()).add(listener);
|
||||
TabooLibAPI.debug("Listener " + listener.getClass().getSimpleName() + " setup successfully. (" + plugin.getName() + ")");
|
||||
} catch (Exception e) {
|
||||
TLogger.getGlobalLogger().warn("TListener setup Failed: " + pluginClass.getName());
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
TabooLibAPI.debug("Listener " + pluginClass.getSimpleName() + "(" + plugin.getName() + ")" + " setup failed: " + e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册所有插件的所有监听器
|
||||
*/
|
||||
public static void registerListeners() {
|
||||
for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
|
||||
try {
|
||||
registerListener(plugin);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册插件的所有监听器
|
||||
* 该操作会执行 TListener 注解中的 register() 对应方法
|
||||
*
|
||||
* @param plugin 插件
|
||||
*/
|
||||
public static void registerListener(Plugin plugin) {
|
||||
Optional.ofNullable(listeners.get(plugin.getName())).ifPresent(listeners -> {
|
||||
for (Listener listener : listeners) {
|
||||
TListener tListener = listener.getClass().getAnnotation(TListener.class);
|
||||
// 检查注册条件
|
||||
if (!Strings.isBlank(tListener.condition())) {
|
||||
try {
|
||||
Method method = listener.getClass().getDeclaredMethod(tListener.condition());
|
||||
method.setAccessible(true);
|
||||
if (!(boolean) method.invoke(listener)) {
|
||||
continue;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
// 执行注册方法
|
||||
if (!Strings.isBlank(tListener.register())) {
|
||||
try {
|
||||
Method method = listener.getClass().getDeclaredMethod(tListener.register());
|
||||
method.setAccessible(true);
|
||||
method.invoke(listener);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
// 注册监听
|
||||
Bukkit.getPluginManager().registerEvents(listener, plugin);
|
||||
TabooLibAPI.debug("Listener " + listener.getClass().getSimpleName() + " registered. (" + plugin.getName() + ")");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 注销所有插件的所有监听器
|
||||
*/
|
||||
public static void cancelListeners() {
|
||||
for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
|
||||
try {
|
||||
cancelListener(plugin);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 注销插件的所有监听器
|
||||
* 该操作会执行 TListener 注解中的 cancel() 对应方法
|
||||
*
|
||||
* @param plugin 插件
|
||||
*/
|
||||
public static void cancelListener(Plugin plugin) {
|
||||
Optional.ofNullable(listeners.remove(plugin.getName())).ifPresent(listeners -> {
|
||||
for (Listener listener : listeners) {
|
||||
HandlerList.unregisterAll(listener);
|
||||
TListener tListener = listener.getClass().getAnnotation(TListener.class);
|
||||
if (!Strings.isBlank(tListener.cancel())) {
|
||||
try {
|
||||
Method method = listener.getClass().getDeclaredMethod(tListener.cancel());
|
||||
method.setAccessible(true);
|
||||
method.invoke(listener);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static HashMap<String, List<Listener>> getListeners() {
|
||||
return listeners;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package io.izzel.taboolib.module.inject;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @Author 坏黑
|
||||
* @Since 2018-12-15 15:07
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface TSchedule {
|
||||
|
||||
int delay() default 0;
|
||||
int period() default -1;
|
||||
|
||||
boolean async() default false;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package io.izzel.taboolib.module.inject;
|
||||
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
/**
|
||||
* @Author 坏黑
|
||||
* @Since 2018-12-15 15:25
|
||||
*/
|
||||
public class TScheduleData {
|
||||
|
||||
private final TSchedule annotation;
|
||||
private final BukkitRunnable runnable;
|
||||
|
||||
public TScheduleData(TSchedule annotation, BukkitRunnable runnable) {
|
||||
this.annotation = annotation;
|
||||
this.runnable = runnable;
|
||||
}
|
||||
|
||||
public TSchedule getAnnotation() {
|
||||
return annotation;
|
||||
}
|
||||
|
||||
public BukkitRunnable getRunnable() {
|
||||
return runnable;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package io.izzel.taboolib.module.inject;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import io.izzel.taboolib.TabooLib;
|
||||
import io.izzel.taboolib.TabooLibLoader;
|
||||
import io.izzel.taboolib.module.logger.TLogger;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Author 坏黑
|
||||
* @Since 2018-12-15 15:09
|
||||
*/
|
||||
public class TScheduleLoader implements TabooLibLoader.Loader {
|
||||
|
||||
static Map<String, List<TScheduleData>> schedules = Maps.newHashMap();
|
||||
|
||||
public static void run(Plugin plugin, BukkitRunnable runnable, int delay, int period, boolean async) {
|
||||
if (async) {
|
||||
runnable.runTaskTimerAsynchronously(plugin, delay, period);
|
||||
} else {
|
||||
runnable.runTaskTimer(plugin, delay, period);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postLoad(Plugin plugin, Class<?> loadClass) {
|
||||
for (Method method : loadClass.getDeclaredMethods()) {
|
||||
TSchedule annotation = method.getAnnotation(TSchedule.class);
|
||||
if (annotation == null) {
|
||||
continue;
|
||||
}
|
||||
Object instance = loadClass.equals(plugin.getClass()) ? plugin : null;
|
||||
// 如果是非静态类型
|
||||
if (!Modifier.isStatic(method.getModifiers()) && instance == null) {
|
||||
// 是否为主类
|
||||
TLogger.getGlobalLogger().error(method.getName() + " is not a static method.");
|
||||
continue;
|
||||
}
|
||||
method.setAccessible(true);
|
||||
// 如果是本插件
|
||||
if (plugin.equals(TabooLib.getPlugin())) {
|
||||
run(plugin, new BukkitRunnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
method.invoke(instance);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
}, annotation.delay(), annotation.period(), annotation.async());
|
||||
}
|
||||
// 其他插件则添加到列队
|
||||
else {
|
||||
schedules.computeIfAbsent(plugin.getName(), n -> Lists.newArrayList()).add(new TScheduleData(annotation, new BukkitRunnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
method.invoke(instance);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
193
src/main/scala/io/izzel/taboolib/module/item/ItemBuilder.java
Normal file
193
src/main/scala/io/izzel/taboolib/module/item/ItemBuilder.java
Normal file
@@ -0,0 +1,193 @@
|
||||
package io.izzel.taboolib.module.item;
|
||||
|
||||
import io.izzel.taboolib.Version;
|
||||
import io.izzel.taboolib.locale.TLocale;
|
||||
import io.izzel.taboolib.util.ArrayUtil;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.block.banner.Pattern;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.inventory.ItemFlag;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.*;
|
||||
import org.bukkit.potion.PotionData;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-08-22 11:37
|
||||
* @BuilderVersion 1.1
|
||||
*/
|
||||
public class ItemBuilder {
|
||||
|
||||
private ItemStack itemStack;
|
||||
private ItemMeta itemMeta;
|
||||
|
||||
public ItemBuilder(Material material) {
|
||||
this(material, 1, 0);
|
||||
}
|
||||
|
||||
public ItemBuilder(Material material, int amount) {
|
||||
this(material, amount, 0);
|
||||
}
|
||||
|
||||
public ItemBuilder(Material material, int amount, int damage) {
|
||||
itemStack = new ItemStack(material, amount, (short) damage);
|
||||
itemMeta = itemStack.getItemMeta();
|
||||
}
|
||||
|
||||
public ItemBuilder(ItemStack itemStack) {
|
||||
this.itemStack = itemStack;
|
||||
this.itemMeta = itemStack.getItemMeta();
|
||||
}
|
||||
|
||||
public ItemBuilder(OfflinePlayer player) {
|
||||
this(Material.SKULL_ITEM, 1, 3);
|
||||
this.skullOwner(player.getName());
|
||||
}
|
||||
|
||||
public ItemBuilder material(int id) {
|
||||
itemStack.setType(Material.getMaterial(id));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemBuilder material(String material) {
|
||||
itemStack.setType(Material.getMaterial(material));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemBuilder material(Material material) {
|
||||
itemStack.setType(material);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemBuilder amount(int amount) {
|
||||
itemStack.setAmount(amount);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemBuilder damage(int damage) {
|
||||
itemStack.setDurability((short) damage);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemBuilder name(String name) {
|
||||
itemMeta.setDisplayName(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemBuilder lore(List<String> lore) {
|
||||
itemMeta.setLore(lore);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemBuilder lore(String... lore) {
|
||||
itemMeta.setLore(ArrayUtil.asList(lore));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemBuilder flags(ItemFlag... flags) {
|
||||
itemMeta.addItemFlags(flags);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemBuilder enchant(Enchantment enchantment, int level) {
|
||||
return enchant(enchantment, level, false);
|
||||
}
|
||||
|
||||
public ItemBuilder enchant(Enchantment enchantment, int level, boolean bypass) {
|
||||
itemMeta.addEnchant(enchantment, level, bypass);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemBuilder shiny() {
|
||||
return enchant(Enchantment.LURE, 1, true).flags(ItemFlag.values());
|
||||
}
|
||||
|
||||
public ItemBuilder color(Color color) {
|
||||
if (itemMeta instanceof LeatherArmorMeta) {
|
||||
((LeatherArmorMeta) itemMeta).setColor(color);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemBuilder banner(Pattern... patterns) {
|
||||
if (itemMeta instanceof BannerMeta) {
|
||||
java.util.Arrays.stream(patterns).forEach(pattern -> ((BannerMeta) itemMeta).addPattern(pattern));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemBuilder potionData(PotionData potionData) {
|
||||
if (itemMeta instanceof PotionMeta) {
|
||||
((PotionMeta) itemMeta).setBasePotionData(potionData);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemBuilder potionColor(Color color) {
|
||||
if (itemMeta instanceof PotionMeta) {
|
||||
((PotionMeta) itemMeta).setColor(color);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemBuilder potionEffect(PotionEffect potionEffect) {
|
||||
if (itemMeta instanceof PotionMeta) {
|
||||
((PotionMeta) itemMeta).addCustomEffect(potionEffect, false);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemBuilder potionEffect(PotionEffect potionEffect, boolean b) {
|
||||
if (itemMeta instanceof PotionMeta) {
|
||||
((PotionMeta) itemMeta).addCustomEffect(potionEffect, b);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemBuilder eggType(EntityType entityType) {
|
||||
if (itemMeta instanceof SpawnEggMeta) {
|
||||
((SpawnEggMeta) itemMeta).setSpawnedType(entityType);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemBuilder skullOwner(String name) {
|
||||
if (itemMeta instanceof SkullMeta) {
|
||||
((SkullMeta) itemMeta).setOwner(name);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemBuilder unbreakable(boolean value) {
|
||||
if (Version.isAfter(Version.v1_12)) {
|
||||
itemMeta.setUnbreakable(value);
|
||||
} else {
|
||||
itemMeta.spigot().setUnbreakable(value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemBuilder colored() {
|
||||
if (itemMeta.hasDisplayName()) {
|
||||
itemMeta.setDisplayName(TLocale.Translate.setColored(itemMeta.getDisplayName()));
|
||||
}
|
||||
if (itemMeta.hasLore()) {
|
||||
itemMeta.setLore(TLocale.Translate.setColored(itemMeta.getLore()));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStack build() {
|
||||
ItemStack buildItem = itemStack.clone();
|
||||
if (itemMeta != null) {
|
||||
buildItem.setItemMeta(itemMeta.clone());
|
||||
}
|
||||
return buildItem;
|
||||
}
|
||||
}
|
||||
286
src/main/scala/io/izzel/taboolib/module/item/Items.java
Normal file
286
src/main/scala/io/izzel/taboolib/module/item/Items.java
Normal file
@@ -0,0 +1,286 @@
|
||||
package io.izzel.taboolib.module.item;
|
||||
|
||||
import io.izzel.taboolib.Version;
|
||||
import io.izzel.taboolib.locale.TLocale;
|
||||
import io.izzel.taboolib.module.lite.SimpleI18n;
|
||||
import io.izzel.taboolib.module.nms.NMSHandler;
|
||||
import io.izzel.taboolib.module.nms.nbt.NBTBase;
|
||||
import io.izzel.taboolib.module.nms.nbt.NBTCompound;
|
||||
import io.izzel.taboolib.module.nms.nbt.NBTList;
|
||||
import io.izzel.taboolib.origin.lite.Numbers;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemFlag;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.inventory.meta.LeatherArmorMeta;
|
||||
import org.bukkit.inventory.meta.PotionMeta;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.bukkit.util.NumberConversions;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author 坏黑
|
||||
* @Since 2019-07-05 16:44
|
||||
*/
|
||||
public class Items {
|
||||
|
||||
public final static Integer[] INVENTORY_CENTER = {
|
||||
10, 11, 12, 13, 14, 15, 16,
|
||||
19, 20, 21, 22, 23, 24, 25,
|
||||
28, 29, 30, 31, 32, 33, 34,
|
||||
37, 38, 39, 40, 41, 42, 43
|
||||
};
|
||||
|
||||
public static String getName(ItemStack item) {
|
||||
return SimpleI18n.getCustomName(item);
|
||||
}
|
||||
|
||||
public static boolean isNull(ItemStack item) {
|
||||
return item == null || item.getType().equals(Material.AIR);
|
||||
}
|
||||
|
||||
public static boolean hasLore(ItemStack i, String a) {
|
||||
return hasLore(i) && i.getItemMeta().getLore().toString().contains(a);
|
||||
}
|
||||
|
||||
public static boolean hasLore(ItemStack i) {
|
||||
return !isNull(i) && i.getItemMeta().hasLore();
|
||||
}
|
||||
|
||||
public static boolean hasName(ItemStack i) {
|
||||
return !isNull(i) && i.getItemMeta().hasDisplayName();
|
||||
}
|
||||
|
||||
public static Material asMaterial(String args) {
|
||||
try {
|
||||
Material material = Material.getMaterial(args.toUpperCase());
|
||||
return material != null ? material : Material.getMaterial(Integer.valueOf(args));
|
||||
} catch (Exception e) {
|
||||
return Material.STONE;
|
||||
}
|
||||
}
|
||||
|
||||
public static Enchantment asEnchantment(String enchant) {
|
||||
try {
|
||||
Enchantment enchantment = Enchantment.getByName(enchant);
|
||||
return enchantment != null ? enchantment : Enchantment.getById(Integer.valueOf(enchant));
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static PotionEffectType asPotionEffectType(String potion) {
|
||||
try {
|
||||
PotionEffectType type = PotionEffectType.getByName(potion);
|
||||
return type != null ? type : PotionEffectType.getById(Integer.valueOf(potion));
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static ItemFlag asItemFlag(String flag) {
|
||||
try {
|
||||
return ItemFlag.valueOf(flag);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Color asColor(String color) {
|
||||
try {
|
||||
return Color.fromBGR(Integer.valueOf(color.split("-")[0]), Integer.valueOf(color.split("-")[1]), Integer.valueOf(color.split("-")[2]));
|
||||
} catch (Exception e) {
|
||||
return Color.fromBGR(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public static String asAttribute(String name) {
|
||||
switch (name.toLowerCase()) {
|
||||
case "damage":
|
||||
return "generic.attackDamage";
|
||||
case "attackspeed":
|
||||
return "generic.attackSpeed";
|
||||
case "health":
|
||||
return "generic.maxHealth";
|
||||
case "speed":
|
||||
return "generic.movementSpeed";
|
||||
case "knockback":
|
||||
return "generic.knockbackResistance";
|
||||
case "armor":
|
||||
return "generic.armor";
|
||||
case "luck":
|
||||
return "generic.luck";
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static ItemStack replaceLore(ItemStack item, String loreOld, String loreNew) {
|
||||
if (hasLore(item)) {
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
List<String> lore = meta.getLore();
|
||||
for (int i = 0; i < lore.size(); i++) {
|
||||
lore.set(i, lore.get(i).replace(loreOld, loreNew));
|
||||
}
|
||||
meta.setLore(lore);
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
public static boolean checkItem(Player player, ItemStack item, int amount, boolean remove) {
|
||||
return checkItem(player.getInventory(), item, amount, remove);
|
||||
}
|
||||
|
||||
public static boolean checkItem(Inventory inventory, ItemStack item, int amount, boolean remove) {
|
||||
int hasAmount = 0;
|
||||
for (ItemStack _item : inventory) {
|
||||
if (item.isSimilar(_item)) {
|
||||
hasAmount += _item.getAmount();
|
||||
}
|
||||
}
|
||||
if (hasAmount < amount) {
|
||||
return false;
|
||||
}
|
||||
int requireAmount = amount;
|
||||
for (int i = 0; i < inventory.getSize() && remove; i++) {
|
||||
ItemStack _item = inventory.getItem(i);
|
||||
if (_item != null && _item.isSimilar(item)) {
|
||||
if (_item.getAmount() < requireAmount) {
|
||||
inventory.setItem(i, null);
|
||||
requireAmount -= _item.getAmount();
|
||||
} else if (_item.getAmount() == requireAmount) {
|
||||
inventory.setItem(i, null);
|
||||
return true;
|
||||
} else {
|
||||
_item.setAmount(_item.getAmount() - requireAmount);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static ItemStack loadItem(ConfigurationSection section) {
|
||||
if (section.get("bukkit") instanceof ItemStack) {
|
||||
return section.getItemStack("bukkit");
|
||||
}
|
||||
// 材质
|
||||
ItemStack item = new ItemStack(asMaterial(section.getString("material")));
|
||||
// 数量
|
||||
item.setAmount(section.contains("amount") ? section.getInt("amount") : 1);
|
||||
// 耐久
|
||||
item.setDurability((short) section.getInt("data"));
|
||||
// 元数据
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
// 展示名
|
||||
if (section.contains("name")) {
|
||||
meta.setDisplayName(section.getString("name"));
|
||||
}
|
||||
// 描述
|
||||
if (section.contains("lore")) {
|
||||
meta.setLore(section.getStringList("lore"));
|
||||
}
|
||||
// 附魔
|
||||
if (section.contains("enchant")) {
|
||||
for (String preEnchant : section.getConfigurationSection("enchant").getKeys(false)) {
|
||||
Enchantment enchant = asEnchantment(preEnchant);
|
||||
if (enchant != null) {
|
||||
meta.addEnchant(enchant, section.getInt("enchant." + preEnchant), true);
|
||||
} else {
|
||||
TLocale.Logger.error("ITEM-UTILS.FAIL-LOAD-ENCHANTS", preEnchant);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 标签
|
||||
if (section.contains("flags") && Version.isAfter(Version.v1_8)) {
|
||||
for (String preFlag : section.getStringList("flags")) {
|
||||
ItemFlag flag = asItemFlag(preFlag);
|
||||
if (flag != null) {
|
||||
meta.addItemFlags(flag);
|
||||
} else {
|
||||
TLocale.Logger.error("ITEM-UTILS.FAIL-LOAD-FLAG", preFlag);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 皮革
|
||||
if (meta instanceof LeatherArmorMeta && section.contains("color")) {
|
||||
((LeatherArmorMeta) meta).setColor(asColor(section.getString("color")));
|
||||
}
|
||||
// 药水
|
||||
if (meta instanceof PotionMeta && section.contains("potions")) {
|
||||
PotionMeta potionMeta = (PotionMeta) meta;
|
||||
for (String prePotionName : section.getConfigurationSection("potions").getKeys(false)) {
|
||||
PotionEffectType potionEffectType = asPotionEffectType(prePotionName);
|
||||
if (potionEffectType != null) {
|
||||
potionMeta.addCustomEffect(new PotionEffect(
|
||||
potionEffectType,
|
||||
NumberConversions.toInt(section.getString("potions." + prePotionName).split("-")[0]),
|
||||
NumberConversions.toInt(section.getString("potions." + prePotionName).split("-")[1]) - 1), true);
|
||||
} else {
|
||||
TLocale.Logger.error("ITEM-UTILS.FAIL-LOAD-POTION", prePotionName);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 元数据
|
||||
item.setItemMeta(meta);
|
||||
// 数据
|
||||
NBTCompound nbt = NMSHandler.getHandler().loadNBT(item);
|
||||
// 物品标签
|
||||
if (section.contains("nbt")) {
|
||||
for (String name : section.getConfigurationSection("nbt").getKeys(false)) {
|
||||
Object obj = section.get("nbt." + name);
|
||||
if (obj instanceof String) {
|
||||
nbt.put(name, new NBTBase(obj.toString()));
|
||||
} else if (obj instanceof Double) {
|
||||
nbt.put(name, new NBTBase(NumberConversions.toDouble(obj)));
|
||||
} else if (obj instanceof Integer) {
|
||||
nbt.put(name, new NBTBase(NumberConversions.toInt(obj)));
|
||||
} else if (obj instanceof Long) {
|
||||
nbt.put(name, new NBTBase(NumberConversions.toLong(obj)));
|
||||
}
|
||||
}
|
||||
}
|
||||
// 物品属性
|
||||
if (section.contains("attributes")) {
|
||||
NBTList attr = new NBTList();
|
||||
for (String hand : section.getConfigurationSection("attributes").getKeys(false)) {
|
||||
for (String name : section.getConfigurationSection("attributes." + hand).getKeys(false)) {
|
||||
if (asAttribute(name) != null) {
|
||||
try {
|
||||
NBTCompound a = new NBTCompound();
|
||||
String num = section.getString("attributes." + hand + "." + name);
|
||||
if (num.endsWith("%")) {
|
||||
a.put("Amount", new NBTBase(NumberConversions.toDouble(num.substring(0, num.length() - 1)) / 100D));
|
||||
a.put("Operation", new NBTBase(1));
|
||||
} else {
|
||||
a.put("Amount", new NBTBase(NumberConversions.toDouble(num)));
|
||||
a.put("Operation", new NBTBase(0));
|
||||
}
|
||||
a.put("AttributeName", new NBTBase(asAttribute(name)));
|
||||
a.put("UUIDMost", new NBTBase(Numbers.getRandom().nextInt(Integer.MAX_VALUE)));
|
||||
a.put("UUIDLeast", new NBTBase(Numbers.getRandom().nextInt(Integer.MAX_VALUE)));
|
||||
a.put("Name", new NBTBase(asAttribute(name)));
|
||||
if (!hand.equals("all")) {
|
||||
a.put("Slot", new NBTBase(hand));
|
||||
}
|
||||
attr.add(a);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
} else {
|
||||
TLocale.Logger.error("ITEM-UTILS.FAIL-LOAD-POTION", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
nbt.put("AttributeModifiers", attr);
|
||||
}
|
||||
return NMSHandler.getHandler().saveNBT(item, nbt);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package io.izzel.taboolib.module.item.inventory;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryDragEvent;
|
||||
import org.bukkit.event.inventory.InventoryInteractEvent;
|
||||
|
||||
/**
|
||||
* @Author 坏黑
|
||||
* @Since 2019-05-21 18:09
|
||||
*/
|
||||
public class ClickEvent {
|
||||
|
||||
private ClickType clickType;
|
||||
private Event event;
|
||||
private char slot;
|
||||
|
||||
public ClickEvent(ClickType clickType, Event event, char slot) {
|
||||
this.clickType = clickType;
|
||||
this.event = event;
|
||||
this.slot = slot;
|
||||
}
|
||||
|
||||
public InventoryClickEvent castClick() {
|
||||
return (InventoryClickEvent) event;
|
||||
}
|
||||
|
||||
public InventoryDragEvent castDrag() {
|
||||
return (InventoryDragEvent) event;
|
||||
}
|
||||
|
||||
public char getSlot() {
|
||||
return slot;
|
||||
}
|
||||
|
||||
public ClickType getClickType() {
|
||||
return clickType;
|
||||
}
|
||||
|
||||
public Player getClicker() {
|
||||
return (Player) ((InventoryInteractEvent) event).getWhoClicked();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package io.izzel.taboolib.module.item.inventory;
|
||||
|
||||
import io.izzel.taboolib.module.inject.TListener;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.event.inventory.InventoryDragEvent;
|
||||
import org.bukkit.event.player.PlayerDropItemEvent;
|
||||
import org.bukkit.event.player.PlayerItemHeldEvent;
|
||||
import org.bukkit.event.server.PluginDisableEvent;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @Author 坏黑
|
||||
* @Since 2019-05-21 18:16
|
||||
*/
|
||||
@TListener
|
||||
class ClickListener implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onDisable(PluginDisableEvent e) {
|
||||
Bukkit.getOnlinePlayers().stream().filter(player -> player.getOpenInventory().getTopInventory().getHolder() instanceof MenuHolder && e.getPlugin().equals(((MenuHolder) player.getOpenInventory().getTopInventory().getHolder()).getBuilder().getPlugin())).forEach(HumanEntity::closeInventory);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onClick(InventoryClickEvent e) {
|
||||
if (e.getInventory().getHolder() instanceof MenuHolder) {
|
||||
if (((MenuHolder) e.getInventory().getHolder()).getBuilder().isLockHand() && (e.getRawSlot() - e.getInventory().getSize() - 27 == e.getWhoClicked().getInventory().getHeldItemSlot() || (e.getClick() == org.bukkit.event.inventory.ClickType.NUMBER_KEY && e.getHotbarButton() == e.getWhoClicked().getInventory().getHeldItemSlot()))) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
Optional.ofNullable(((MenuHolder) e.getInventory().getHolder()).getBuilder().getClickTask()).ifPresent(t -> t.run(new ClickEvent(ClickType.CLICK, e, ((MenuHolder) e.getInventory().getHolder()).getBuilder().getSlot(e.getRawSlot()))));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onDrag(InventoryDragEvent e) {
|
||||
if (e.getInventory().getHolder() instanceof MenuHolder) {
|
||||
Optional.ofNullable(((MenuHolder) e.getInventory().getHolder()).getBuilder().getClickTask()).ifPresent(t -> t.run(new ClickEvent(ClickType.DRAG, e, ' ')));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onDrag(InventoryCloseEvent e) {
|
||||
if (e.getInventory().getHolder() instanceof MenuHolder) {
|
||||
Optional.ofNullable(((MenuHolder) e.getInventory().getHolder()).getBuilder().getCloseTask()).ifPresent(t -> t.run(e));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onDrop(PlayerDropItemEvent e) {
|
||||
if (e.getPlayer().getOpenInventory().getTopInventory().getHolder() instanceof MenuHolder && ((MenuHolder) e.getPlayer().getOpenInventory().getTopInventory().getHolder()).getBuilder().isLockHand()) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onHeld(PlayerItemHeldEvent e) {
|
||||
if (e.getPlayer().getOpenInventory().getTopInventory().getHolder() instanceof MenuHolder && ((MenuHolder) e.getPlayer().getOpenInventory().getTopInventory().getHolder()).getBuilder().isLockHand()) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package io.izzel.taboolib.module.item.inventory;
|
||||
|
||||
import io.izzel.taboolib.module.inject.TListener;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerSwapHandItemsEvent;
|
||||
|
||||
/**
|
||||
* @Author 坏黑
|
||||
* @Since 2019-05-21 22:04
|
||||
*/
|
||||
@TListener(version = ">=10900")
|
||||
class ClickListenerOffhand implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onSwap(PlayerSwapHandItemsEvent e) {
|
||||
if (e.getPlayer().getOpenInventory().getTopInventory().getHolder() instanceof MenuHolder && ((MenuHolder) e.getPlayer().getOpenInventory().getTopInventory().getHolder()).getBuilder().isLockHand()) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package io.izzel.taboolib.module.item.inventory;
|
||||
|
||||
/**
|
||||
* @Author 坏黑
|
||||
* @Since 2019-05-21 18:14
|
||||
*/
|
||||
public interface ClickTask {
|
||||
|
||||
void run(ClickEvent event);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package io.izzel.taboolib.module.item.inventory;
|
||||
|
||||
/**
|
||||
* @Author 坏黑
|
||||
* @Since 2019-05-21 18:10
|
||||
*/
|
||||
public enum ClickType {
|
||||
|
||||
CLICK, DRAG
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package io.izzel.taboolib.module.item.inventory;
|
||||
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
|
||||
/**
|
||||
* @Author 坏黑
|
||||
* @Since 2019-05-21 18:14
|
||||
*/
|
||||
public interface CloseTask {
|
||||
|
||||
void run(InventoryCloseEvent event);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
package io.izzel.taboolib.module.item.inventory;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import io.izzel.taboolib.TabooLib;
|
||||
import io.izzel.taboolib.util.Ref;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Author 坏黑
|
||||
* @Since 2019-05-21 15:54
|
||||
*/
|
||||
public class MenuBuilder {
|
||||
|
||||
private Map<Character, ItemStack> keys = Maps.newHashMap();
|
||||
private Plugin plugin;
|
||||
private String title;
|
||||
private int rows;
|
||||
private char[][] items ;
|
||||
private ClickTask clickTask;
|
||||
private CloseTask closeTask;
|
||||
private boolean lockHand;
|
||||
|
||||
public MenuBuilder(Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public static MenuBuilder builder(Plugin plugin) {
|
||||
return new MenuBuilder(plugin);
|
||||
}
|
||||
|
||||
public static MenuBuilder builder() {
|
||||
return new MenuBuilder(Ref.getCallerPlugin(Ref.getCallerClass(3).orElse(TabooLib.class)));
|
||||
}
|
||||
|
||||
public MenuBuilder lockHand() {
|
||||
this.lockHand = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MenuBuilder event(ClickTask clickTask) {
|
||||
this.clickTask = clickTask;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MenuBuilder close(CloseTask closeTask) {
|
||||
this.closeTask = closeTask;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MenuBuilder title(String title) {
|
||||
this.title = title;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MenuBuilder rows(int rows) {
|
||||
this.rows = rows * 9;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MenuBuilder put(char key, ItemStack item) {
|
||||
keys.put(key, item);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MenuBuilder items(String... placeholder) {
|
||||
items = new char[placeholder.length][];
|
||||
for (int i = 0; i < placeholder.length; i++) {
|
||||
items[i] = placeholder[i].toCharArray();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Inventory build() {
|
||||
Inventory inventory = Bukkit.createInventory(new MenuHolder(this), rows, String.valueOf(title));
|
||||
for (int i = 0; i < items.length && i < rows; i++) {
|
||||
char[] line = items[i];
|
||||
for (int j = 0; j < line.length && j < 9; j++) {
|
||||
inventory.setItem(i * 9 + j, keys.getOrDefault(line[j], new ItemStack(Material.AIR)));
|
||||
}
|
||||
}
|
||||
return inventory;
|
||||
}
|
||||
|
||||
public char getSlot(int slot) {
|
||||
for (int i = 0; i < items.length && i < rows; i++) {
|
||||
char[] line = items[i];
|
||||
for (int j = 0; j < line.length && j < 9; j++) {
|
||||
if (i * 9 + j == slot) {
|
||||
return line[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
return ' ';
|
||||
}
|
||||
|
||||
// *********************************
|
||||
//
|
||||
// Getter and Setter
|
||||
//
|
||||
// *********************************
|
||||
|
||||
public Map<Character, ItemStack> getKeys() {
|
||||
return keys;
|
||||
}
|
||||
|
||||
public Plugin getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public int getRows() {
|
||||
return rows;
|
||||
}
|
||||
|
||||
public char[][] getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
public ClickTask getClickTask() {
|
||||
return clickTask;
|
||||
}
|
||||
|
||||
public CloseTask getCloseTask() {
|
||||
return closeTask;
|
||||
}
|
||||
|
||||
public boolean isLockHand() {
|
||||
return lockHand;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package io.izzel.taboolib.module.item.inventory;
|
||||
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
|
||||
/**
|
||||
* @Author 坏黑
|
||||
* @Since 2019-05-21 20:28
|
||||
*/
|
||||
class MenuHolder implements InventoryHolder {
|
||||
|
||||
private MenuBuilder builder;
|
||||
|
||||
public MenuHolder(MenuBuilder builder) {
|
||||
this.builder = builder;
|
||||
}
|
||||
|
||||
public MenuBuilder getBuilder() {
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Inventory getInventory() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package io.izzel.taboolib.module.lite;
|
||||
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.FieldVisitor;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
/**
|
||||
* 我不信 ClassNotFoundException 的邪,自己写了一个发现还是一样。。。
|
||||
*
|
||||
* @Author sky
|
||||
* @Since 2018-09-19 21:17
|
||||
*/
|
||||
public class SimpleClassVisitor extends ClassVisitor {
|
||||
|
||||
private final SimpleVersionControl simpleVersionControl;
|
||||
|
||||
public SimpleClassVisitor(SimpleVersionControl simpleVersionControl, ClassVisitor classVisitor) {
|
||||
super(Opcodes.ASM5, classVisitor);
|
||||
this.simpleVersionControl = simpleVersionControl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
|
||||
super.visit(version, access, translate(name), translate(signature), translate(superName), translate(interfaces));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClass(String name, String outerName, String innerName, int access) {
|
||||
super.visitInnerClass(translate(name), translate(outerName), translate(innerName), access);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
|
||||
return super.visitField(access, translate(name), translate(descriptor), translate(signature), value instanceof String ? translate((String) value) : value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOuterClass(String owner, String name, String descriptor) {
|
||||
super.visitOuterClass(translate(owner), translate(name), translate(descriptor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
|
||||
return new SimpleMethodVisitor(simpleVersionControl, super.visitMethod(access, translate(name), translate(descriptor), translate(signature), translate(exceptions)));
|
||||
}
|
||||
|
||||
private String translate(String target) {
|
||||
return target == null ? null : simpleVersionControl.replace(target);
|
||||
}
|
||||
|
||||
private String[] translate(String[] target) {
|
||||
if (target == null) {
|
||||
return target;
|
||||
}
|
||||
IntStream.range(0, target.length).forEach(i -> target[i] = translate(target[i]));
|
||||
return target;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package io.izzel.taboolib.module.lite;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-09-25 15:21
|
||||
*/
|
||||
public class SimpleCounter {
|
||||
|
||||
private int timer;
|
||||
private int limit;
|
||||
private boolean ignoredFirst;
|
||||
private boolean counterFirst;
|
||||
|
||||
public SimpleCounter(int limit) {
|
||||
this(limit, false);
|
||||
}
|
||||
|
||||
public SimpleCounter(int limit, boolean ignoredFirst) {
|
||||
this.timer = 0;
|
||||
this.limit = limit;
|
||||
this.ignoredFirst = ignoredFirst;
|
||||
this.counterFirst = true;
|
||||
}
|
||||
|
||||
public boolean next() {
|
||||
if (--timer <= 0) {
|
||||
timer = limit;
|
||||
if (ignoredFirst && counterFirst) {
|
||||
counterFirst = false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
timer = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package io.izzel.taboolib.module.lite;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Author 坏黑
|
||||
* @Since 2019-04-25 22:01
|
||||
*/
|
||||
public enum SimpleEquip {
|
||||
|
||||
HAND(EquipmentSlot.HAND, -1),
|
||||
|
||||
OFF_HAND(EquipmentSlot.OFF_HAND, 40),
|
||||
|
||||
FEET(EquipmentSlot.FEET, 36),
|
||||
|
||||
LEGS(EquipmentSlot.LEGS, 37),
|
||||
|
||||
CHEST(EquipmentSlot.CHEST, 38),
|
||||
|
||||
HEAD(EquipmentSlot.HEAD, 39);
|
||||
|
||||
private EquipmentSlot bukkit;
|
||||
private int slot;
|
||||
|
||||
SimpleEquip(EquipmentSlot bukkit, int slot) {
|
||||
this.bukkit = bukkit;
|
||||
this.slot = slot;
|
||||
}
|
||||
|
||||
public void setItem(Player player, ItemStack item) {
|
||||
if (this != HAND) {
|
||||
player.getInventory().setItem(slot, item);
|
||||
} else {
|
||||
player.setItemInHand(item);
|
||||
}
|
||||
}
|
||||
|
||||
public ItemStack getItem(Player player) {
|
||||
if (this != HAND) {
|
||||
return player.getInventory().getItem(slot);
|
||||
} else {
|
||||
return player.getItemInHand();
|
||||
}
|
||||
}
|
||||
|
||||
public static SimpleEquip fromBukkit(EquipmentSlot bukkit) {
|
||||
return Arrays.stream(values()).filter(tEquipment -> tEquipment.bukkit == bukkit).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
public static Map<SimpleEquip, ItemStack> getItems(Player player) {
|
||||
Map<SimpleEquip, ItemStack> map = Maps.newHashMap();
|
||||
for (SimpleEquip equipment : values()) {
|
||||
map.put(equipment, equipment.getItem(player));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// *********************************
|
||||
//
|
||||
// Getter and Setter
|
||||
//
|
||||
// *********************************
|
||||
|
||||
public EquipmentSlot getBukkit() {
|
||||
return bukkit;
|
||||
}
|
||||
|
||||
public int getSlot() {
|
||||
return slot;
|
||||
}
|
||||
}
|
||||
101
src/main/scala/io/izzel/taboolib/module/lite/SimpleI18n.java
Normal file
101
src/main/scala/io/izzel/taboolib/module/lite/SimpleI18n.java
Normal file
@@ -0,0 +1,101 @@
|
||||
package io.izzel.taboolib.module.lite;
|
||||
|
||||
import io.izzel.taboolib.TabooLib;
|
||||
import io.izzel.taboolib.Version;
|
||||
import io.izzel.taboolib.locale.TLocaleLoader;
|
||||
import io.izzel.taboolib.module.inject.TFunction;
|
||||
import io.izzel.taboolib.module.nms.NMSHandler;
|
||||
import io.izzel.taboolib.module.nms.nbt.NBTCompound;
|
||||
import io.izzel.taboolib.util.Files;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.BookMeta;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.inventory.meta.SpawnEggMeta;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @Author 坏黑
|
||||
* @Since 2019-05-22 1:16
|
||||
*/
|
||||
@TFunction(enable = "init")
|
||||
public class SimpleI18n {
|
||||
|
||||
private static FileConfiguration lang;
|
||||
private static boolean released;
|
||||
|
||||
static void init() {
|
||||
File localeFile = getLocaleFile(TabooLib.getPlugin());
|
||||
if (localeFile == null) {
|
||||
lang = new YamlConfiguration();
|
||||
} else {
|
||||
lang = Files.load(TabooLib.getPlugin(), localeFile);
|
||||
}
|
||||
if (lang.getInt("version") < 3 && !released) {
|
||||
released = true;
|
||||
Files.deepDelete(new File(TabooLib.getPlugin().getDataFolder(), "simpleI18n"));
|
||||
init();
|
||||
}
|
||||
}
|
||||
|
||||
public static String getCustomName(Entity entity) {
|
||||
return entity != null ? Optional.ofNullable(entity.getCustomName()).orElse(getName(entity)) : getName(entity);
|
||||
}
|
||||
|
||||
public static String getCustomName(ItemStack item) {
|
||||
if (item != null) {
|
||||
ItemMeta itemMeta = item.getItemMeta();
|
||||
return itemMeta != null && itemMeta.hasDisplayName() ? itemMeta.getDisplayName() : getName(item);
|
||||
}
|
||||
return getName(item);
|
||||
}
|
||||
|
||||
public static String getName(Entity entity) {
|
||||
return entity == null ? "-" : lang.getString(NMSHandler.getHandler().getName(entity).replace(".", "_"), entity.getName());
|
||||
}
|
||||
|
||||
public static String getName(ItemStack item) {
|
||||
if (item == null) {
|
||||
return "-";
|
||||
}
|
||||
ItemMeta itemMeta = item.getItemMeta();
|
||||
if (itemMeta instanceof BookMeta && ((BookMeta) itemMeta).getTitle() != null) {
|
||||
return ((BookMeta) itemMeta).getTitle();
|
||||
}
|
||||
if (!Version.isAfter(Version.v1_11)) {
|
||||
if (item.getType().name().equals("MONSTER_EGG")) {
|
||||
NBTCompound nbtCompound = NMSHandler.getHandler().loadNBT(item);
|
||||
if (nbtCompound.containsKey("EntityTag")) {
|
||||
return lang.getString("item_monsterPlacer_name") + " " + lang.getString("entity_" + nbtCompound.get("EntityTag").asCompound().get("id").asString() + "_name");
|
||||
}
|
||||
return lang.getString("item_monsterPlacer_name");
|
||||
}
|
||||
} else if (!Version.isAfter(Version.v1_13)) {
|
||||
if (itemMeta instanceof SpawnEggMeta) {
|
||||
String spawnEggType = lang.getString("entity_" + ((SpawnEggMeta) itemMeta).getSpawnedType().getEntityClass().getSimpleName().replace(".", "_") + "_name");
|
||||
if (spawnEggType != null) {
|
||||
return lang.getString(NMSHandler.getHandler().getName(item).replace(".", "_"), item.getType().name().toLowerCase().replace("_", "")) + " " + spawnEggType;
|
||||
}
|
||||
}
|
||||
}
|
||||
return lang.getString(NMSHandler.getHandler().getName(item).replace(".", "_"), item.getType().name().toLowerCase().replace("_", ""));
|
||||
}
|
||||
|
||||
private static void releaseLocales(Plugin plugin) {
|
||||
TLocaleLoader.getLocalePriority().stream().filter(localeName -> !new File("plugins/TabooLib/simpleI18n/" + getVersion() + "/" + localeName + ".yml").exists() && plugin.getResource("simpleI18n/" + getVersion() + "/" + localeName + ".yml") != null).forEach(localeName -> plugin.saveResource("simpleI18n/" + getVersion() + "/" + localeName + ".yml", true));
|
||||
}
|
||||
|
||||
private static File getLocaleFile(Plugin plugin) {
|
||||
releaseLocales(plugin);
|
||||
return TLocaleLoader.getLocalePriority().stream().map(localeName -> new File("plugins/TabooLib/simpleI18n/" + getVersion() + "/" + localeName + ".yml")).filter(File::exists).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
private static String getVersion() {
|
||||
return Version.isAfter(Version.v1_13) ? "high" : "low";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package io.izzel.taboolib.module.lite;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-10-01 16:19
|
||||
*/
|
||||
public class SimpleIterator {
|
||||
|
||||
private final Object container;
|
||||
|
||||
public SimpleIterator(Object container) {
|
||||
this.container = container;
|
||||
}
|
||||
|
||||
public List<Map.Entry> mapIterator(int start, int end) {
|
||||
List<Map.Entry> iterator = Lists.newArrayList();
|
||||
Map container = (Map) this.container;
|
||||
int loop = 0;
|
||||
for (Object entry : container.entrySet()) {
|
||||
if (loop++ >= start) {
|
||||
if (loop <= end) {
|
||||
iterator.add((Map.Entry) entry);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return iterator;
|
||||
}
|
||||
|
||||
public List listIterator(int start, int end) {
|
||||
List iterator = Lists.newArrayList();
|
||||
List container = (List) this.container;
|
||||
int loop = 0;
|
||||
for (Object entry : container) {
|
||||
if (loop++ >= start) {
|
||||
if (loop <= end) {
|
||||
iterator.add(entry);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return iterator;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package io.izzel.taboolib.module.lite;
|
||||
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
/**
|
||||
* 我不信 ClassNotFound 的邪,自己写了一个发现还是一样。。。
|
||||
*
|
||||
* @Author sky
|
||||
* @Since 2018-9-19 21:33
|
||||
*/
|
||||
public class SimpleMethodVisitor extends MethodVisitor {
|
||||
|
||||
private final SimpleVersionControl simpleVersionControl;
|
||||
|
||||
public SimpleMethodVisitor(SimpleVersionControl simpleVersionControl, MethodVisitor methodVisitor) {
|
||||
super(Opcodes.ASM5, methodVisitor);
|
||||
this.simpleVersionControl = simpleVersionControl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitParameter(String name, int access) {
|
||||
super.visitParameter(translate(name), access);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethodInsn(int opcode, String owner, String name, String descriptor) {
|
||||
super.visitMethodInsn(opcode, translate(owner), translate(name), translate(descriptor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) {
|
||||
super.visitMethodInsn(opcode, translate(owner), translate(name), translate(descriptor), isInterface);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLdcInsn(Object value) {
|
||||
if (value instanceof Type) {
|
||||
super.visitLdcInsn(Type.getType(translate(((Type) value).getDescriptor())));
|
||||
} else {
|
||||
super.visitLdcInsn(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeInsn(int opcode, String type) {
|
||||
super.visitTypeInsn(opcode, translate(type));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitFieldInsn(int opcode, String owner, String name, String descriptor) {
|
||||
super.visitFieldInsn(opcode, translate(owner), translate(name), translate(descriptor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) {
|
||||
super.visitLocalVariable(translate(name), translate(descriptor), translate(signature), start, end, index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInvokeDynamicInsn(String name, String descriptor, Handle bootstrapMethodHandle, Object... bootstrapMethodArguments) {
|
||||
super.visitInvokeDynamicInsn(translate(name), translate(descriptor), bootstrapMethodHandle, bootstrapMethodArguments);
|
||||
}
|
||||
|
||||
private String translate(String target) {
|
||||
return target == null ? null : simpleVersionControl.replace(target);
|
||||
}
|
||||
|
||||
private String[] translate(String[] target) {
|
||||
if (target == null) {
|
||||
return target;
|
||||
}
|
||||
IntStream.range(0, target.length).forEach(i -> target[i] = translate(target[i]));
|
||||
return target;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
package io.izzel.taboolib.module.lite;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Author 坏黑
|
||||
* @Since 2018-10-25 22:51
|
||||
*/
|
||||
public class SimpleReflection {
|
||||
|
||||
private static Map<String, Map<String, Field>> fieldCached = Maps.newHashMap();
|
||||
|
||||
public static boolean isExists(Class<?> nmsClass) {
|
||||
return fieldCached.containsKey(nmsClass.getName());
|
||||
}
|
||||
|
||||
public static Map<String, Field> getFields(Class<?> nmsClass) {
|
||||
return fieldCached.getOrDefault(nmsClass.getName(), Maps.newHashMap());
|
||||
}
|
||||
|
||||
public static Field getField(Class<?> nmsClass, String fieldName) {
|
||||
return fieldCached.getOrDefault(nmsClass.getName(), Maps.newHashMap()).get(fieldName);
|
||||
}
|
||||
|
||||
public static void checkAndSave(Class<?> nmsClass) {
|
||||
if (!isExists(nmsClass)) {
|
||||
saveField(nmsClass);
|
||||
}
|
||||
}
|
||||
|
||||
public static void saveField(Class<?> nmsClass) {
|
||||
try {
|
||||
Arrays.stream(nmsClass.getDeclaredFields()).forEach(declaredField -> saveField(nmsClass, declaredField.getName()));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void saveField(Class<?> nmsClass, String fieldName) {
|
||||
try {
|
||||
Field declaredField = nmsClass.getDeclaredField(fieldName);
|
||||
declaredField.setAccessible(true);
|
||||
fieldCached.computeIfAbsent(nmsClass.getName(), name -> Maps.newHashMap()).put(fieldName, declaredField);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void setFieldValue(Class<?> nmsClass, Object instance, String fieldName, Object value) {
|
||||
try {
|
||||
Map<String, Field> fields = fieldCached.get(nmsClass.getName());
|
||||
if (fields == null) {
|
||||
return;
|
||||
}
|
||||
Field field = fields.get(fieldName);
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
field.set(instance, value);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static Object getFieldValue(Class<?> nmsClass, Object instance, String fieldName) {
|
||||
try {
|
||||
Map<String, Field> fields = fieldCached.get(nmsClass.getName());
|
||||
if (fields == null) {
|
||||
return null;
|
||||
}
|
||||
Field field = fields.get(fieldName);
|
||||
if (field == null) {
|
||||
return null;
|
||||
}
|
||||
return field.get(instance);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T> T getFieldValue(Class<?> nmsClass, Object instance, String fieldName, T def) {
|
||||
try {
|
||||
Map<String, Field> fields = fieldCached.get(nmsClass.getName());
|
||||
if (fields == null) {
|
||||
return def;
|
||||
}
|
||||
Field field = fields.get(fieldName);
|
||||
if (field == null) {
|
||||
return def;
|
||||
}
|
||||
return (T) field.get(instance);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
public static Class getListType(Field field) {
|
||||
Type genericType = field.getGenericType();
|
||||
try {
|
||||
if (ParameterizedType.class.isAssignableFrom(genericType.getClass())) {
|
||||
for (Type actualTypeArgument : ((ParameterizedType) genericType).getActualTypeArguments()) {
|
||||
return Class.forName(actualTypeArgument.getTypeName());
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Class[] getMapType(Field field) {
|
||||
Class[] mapType = new Class[2];
|
||||
try {
|
||||
Type genericType = field.getGenericType();
|
||||
if (ParameterizedType.class.isAssignableFrom(genericType.getClass())) {
|
||||
for (Type actualTypeArgument : ((ParameterizedType) genericType).getActualTypeArguments()) {
|
||||
mapType[mapType[0] == null ? 0 : 1] = Class.forName(actualTypeArgument.getTypeName());
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
return mapType[1] == null ? null : mapType ;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
package io.izzel.taboolib.module.lite;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import io.izzel.taboolib.TabooLib;
|
||||
import io.izzel.taboolib.Version;
|
||||
import io.izzel.taboolib.util.Files;
|
||||
import io.izzel.taboolib.util.asm.AsmClassLoader;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-09-19 21:05
|
||||
*/
|
||||
public class SimpleVersionControl {
|
||||
|
||||
private static Map<String, Class<?>> cacheClasses = new HashMap<>();
|
||||
private String target;
|
||||
private String to;
|
||||
private List<String> from = Lists.newArrayList();
|
||||
private Plugin plugin;
|
||||
private boolean useCache;
|
||||
private boolean useNMS;
|
||||
|
||||
SimpleVersionControl() {
|
||||
useCache = false;
|
||||
}
|
||||
|
||||
public static SimpleVersionControl create() {
|
||||
return new SimpleVersionControl().to(Version.getBukkitVersion()).plugin(TabooLib.getPlugin());
|
||||
}
|
||||
|
||||
public static SimpleVersionControl create(String toVersion) {
|
||||
return new SimpleVersionControl().to(toVersion).plugin(TabooLib.getPlugin());
|
||||
}
|
||||
|
||||
public static SimpleVersionControl createSimple(String target, String... from) {
|
||||
return create().target(target).from(from);
|
||||
}
|
||||
|
||||
public static SimpleVersionControl createNMS(String target) {
|
||||
return create().target(target).useNMS();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置转换类地址,写法如:me.skymc.taboolib.packet.InternalPacket
|
||||
*/
|
||||
public SimpleVersionControl target(String target) {
|
||||
this.target = target;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置原版本,写法如:v1_8_R3
|
||||
*/
|
||||
public SimpleVersionControl from(String from) {
|
||||
this.from.add(from.startsWith("v") ? from : "v" + from);
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* 设置原版本,写法如:v1_8_R3, v1_12_R1
|
||||
*/
|
||||
public SimpleVersionControl from(String... from) {
|
||||
Arrays.stream(from).forEach(v -> this.from.add(v.startsWith("v") ? v : "v" + v));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置目标版本
|
||||
*/
|
||||
public SimpleVersionControl to(String to) {
|
||||
this.to = to.startsWith("v") ? to : "v" + to;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置插件,不填默认指向 TabooLib
|
||||
*/
|
||||
public SimpleVersionControl plugin(Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换类将会保存在 TabooLib 中,防止出现 NoClassDefFoundError 异常
|
||||
*/
|
||||
public SimpleVersionControl useCache() {
|
||||
this.useCache = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动转换所有使用到的 NMS 或 OBC 方法
|
||||
*/
|
||||
public SimpleVersionControl useNMS() {
|
||||
this.useNMS = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Class<?> translate() throws IOException {
|
||||
return translate(plugin);
|
||||
}
|
||||
|
||||
public Class<?> translate(Plugin plugin) throws IOException {
|
||||
if (useCache && cacheClasses.containsKey(target)) {
|
||||
return cacheClasses.get(target);
|
||||
}
|
||||
ClassReader classReader = new ClassReader(Files.getResource(plugin, target.replace(".", "/") + ".class"));
|
||||
ClassWriter classWriter = new ClassWriter(0);
|
||||
ClassVisitor classVisitor = new SimpleClassVisitor(this, classWriter);
|
||||
classReader.accept(classVisitor, ClassReader.EXPAND_FRAMES);
|
||||
classWriter.visitEnd();
|
||||
classVisitor.visitEnd();
|
||||
Class<?> newClass = AsmClassLoader.createNewClass(target, classWriter.toByteArray());
|
||||
if (useCache) {
|
||||
cacheClasses.put(target, newClass);
|
||||
}
|
||||
return newClass;
|
||||
}
|
||||
|
||||
// *********************************
|
||||
//
|
||||
// Getter and Setter
|
||||
//
|
||||
// *********************************
|
||||
|
||||
public String getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
public List<String> getFrom() {
|
||||
return from;
|
||||
}
|
||||
|
||||
public String getTo() {
|
||||
return to;
|
||||
}
|
||||
|
||||
public String replace(String origin) {
|
||||
if (useNMS) {
|
||||
origin = origin.replaceAll("net/minecraft/server/.*?/", "net/minecraft/server/" + to + "/").replaceAll("org/bukkit/craftbukkit/.*?/", "org/bukkit/craftbukkit/" + to + "/");
|
||||
}
|
||||
for (String from : from) {
|
||||
origin = origin.replace("/" + from + "/", "/" + to + "/");
|
||||
}
|
||||
return origin;
|
||||
}
|
||||
}
|
||||
128
src/main/scala/io/izzel/taboolib/module/logger/TLogger.java
Normal file
128
src/main/scala/io/izzel/taboolib/module/logger/TLogger.java
Normal file
@@ -0,0 +1,128 @@
|
||||
package io.izzel.taboolib.module.logger;
|
||||
|
||||
import io.izzel.taboolib.TabooLibAPI;
|
||||
import io.izzel.taboolib.locale.TLocale;
|
||||
import io.izzel.taboolib.util.Strings;
|
||||
import net.md_5.bungee.BungeeCord;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
public class TLogger {
|
||||
|
||||
public static final int VERBOSE = 0, FINEST = 1, FINE = 2, INFO = 3, WARN = 4, ERROR = 5, FATAL = 6;
|
||||
|
||||
private final String pattern;
|
||||
private final String name;
|
||||
private int level;
|
||||
|
||||
public TLogger(String pattern, Plugin plugin, int level) {
|
||||
this.pattern = pattern;
|
||||
this.name = plugin.getName();
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
public TLogger(String pattern, String name, int level) {
|
||||
this.pattern = pattern;
|
||||
this.name = name;
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
public static TLogger getGlobalLogger() {
|
||||
return io.izzel.taboolib.TabooLib.getLogger();
|
||||
}
|
||||
|
||||
public static TLogger getUnformatted(Plugin plugin) {
|
||||
return new TLogger("§8[§3§l{0}§8][§r{1}§8] §f{2}", plugin, TLogger.FINE);
|
||||
}
|
||||
|
||||
public static TLogger getUnformatted(String name) {
|
||||
return new TLogger("§8[§3§l{0}§8][§r{1}§8] §f{2}", name, TLogger.FINE);
|
||||
}
|
||||
|
||||
public String getPattern() {
|
||||
return pattern;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public int getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
public void setLevel(int level) {
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
public void verbose(String msg) {
|
||||
if (level <= VERBOSE) {
|
||||
if (TabooLibAPI.isBukkit()) {
|
||||
Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, name, "§fVERBOSE", TLocale.Translate.setColored(msg)));
|
||||
} else {
|
||||
BungeeCord.getInstance().getConsole().sendMessage(TextComponent.fromLegacyText(Strings.replaceWithOrder(pattern, name, "§fVERBOSE", TLocale.Translate.setColored(msg))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void finest(String msg) {
|
||||
if (level <= FINEST) {
|
||||
if (TabooLibAPI.isBukkit()) {
|
||||
Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, name, "§eFINEST", TLocale.Translate.setColored(msg)));
|
||||
} else {
|
||||
BungeeCord.getInstance().getConsole().sendMessage(TextComponent.fromLegacyText(Strings.replaceWithOrder(pattern, name, "§eFINEST", TLocale.Translate.setColored(msg))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void fine(String msg) {
|
||||
if (level <= FINE) {
|
||||
if (TabooLibAPI.isBukkit()) {
|
||||
Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, name, "§aFINE", TLocale.Translate.setColored(msg)));
|
||||
} else {
|
||||
BungeeCord.getInstance().getConsole().sendMessage(TextComponent.fromLegacyText(Strings.replaceWithOrder(pattern, name, "§aFINE", TLocale.Translate.setColored(msg))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void info(String msg) {
|
||||
if (level <= INFO) {
|
||||
if (TabooLibAPI.isBukkit()) {
|
||||
Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, name, "§bINFO", TLocale.Translate.setColored(msg)));
|
||||
} else {
|
||||
BungeeCord.getInstance().getConsole().sendMessage(TextComponent.fromLegacyText(Strings.replaceWithOrder(pattern, name, "§bINFO", TLocale.Translate.setColored(msg))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void warn(String msg) {
|
||||
if (level <= WARN) {
|
||||
if (TabooLibAPI.isBukkit()) {
|
||||
Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, name, "§6WARN", "§6" + TLocale.Translate.setColored(msg)));
|
||||
} else {
|
||||
BungeeCord.getInstance().getConsole().sendMessage(TextComponent.fromLegacyText(Strings.replaceWithOrder(pattern, name, "§6WARN", "§6" + TLocale.Translate.setColored(msg))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void error(String msg) {
|
||||
if (level <= ERROR) {
|
||||
if (TabooLibAPI.isBukkit()) {
|
||||
Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, name, "§cERROR", "§c" + TLocale.Translate.setColored(msg)));
|
||||
} else {
|
||||
BungeeCord.getInstance().getConsole().sendMessage(TextComponent.fromLegacyText(Strings.replaceWithOrder(pattern, name, "§cERROR", "§c" + TLocale.Translate.setColored(msg))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void fatal(String msg) {
|
||||
if (level <= FATAL) {
|
||||
if (TabooLibAPI.isBukkit()) {
|
||||
Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, name, "§4FATAL", "§4" + TLocale.Translate.setColored(msg)));
|
||||
} else {
|
||||
BungeeCord.getInstance().getConsole().sendMessage(TextComponent.fromLegacyText(Strings.replaceWithOrder(pattern, name, "§4FATAL", "§4" + TLocale.Translate.setColored(msg))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package io.izzel.taboolib.module.logger;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class TLoggerManager {
|
||||
|
||||
private static final Map<Plugin, TLogger> map = new HashMap<>();
|
||||
|
||||
public static void setDefaultLogger(Plugin plugin, TLogger logger) {
|
||||
map.put(plugin, logger);
|
||||
}
|
||||
|
||||
public static TLogger getLogger(Plugin plugin) {
|
||||
TLogger logger = map.get(plugin);
|
||||
if (logger == null) {
|
||||
logger = TLogger.getUnformatted(plugin);
|
||||
map.put(plugin, logger);
|
||||
}
|
||||
return logger;
|
||||
}
|
||||
}
|
||||
11
src/main/scala/io/izzel/taboolib/module/mysql/IColumn.java
Normal file
11
src/main/scala/io/izzel/taboolib/module/mysql/IColumn.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package io.izzel.taboolib.module.mysql;
|
||||
|
||||
/**
|
||||
* @Author 坏黑
|
||||
* @Since 2018-12-08 13:46
|
||||
*/
|
||||
public abstract class IColumn {
|
||||
|
||||
abstract public String convertToCommand();
|
||||
|
||||
}
|
||||
42
src/main/scala/io/izzel/taboolib/module/mysql/IHost.java
Normal file
42
src/main/scala/io/izzel/taboolib/module/mysql/IHost.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package io.izzel.taboolib.module.mysql;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-05-14 19:07
|
||||
*/
|
||||
public abstract class IHost {
|
||||
|
||||
private Plugin plugin;
|
||||
private boolean autoClose;
|
||||
|
||||
public IHost(Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public IHost(Plugin plugin, boolean autoClose) {
|
||||
this.plugin = plugin;
|
||||
this.autoClose = autoClose;
|
||||
}
|
||||
|
||||
public Plugin getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
public void setPlugin(Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public boolean isAutoClose() {
|
||||
return autoClose;
|
||||
}
|
||||
|
||||
public void setAutoClose(boolean autoClose) {
|
||||
this.autoClose = autoClose;
|
||||
}
|
||||
|
||||
abstract public String getConnectionUrl();
|
||||
|
||||
abstract public String getConnectionUrlSimple();
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
package io.izzel.taboolib.module.mysql.builder;
|
||||
|
||||
import io.izzel.taboolib.util.Strings;
|
||||
import io.izzel.taboolib.module.mysql.IColumn;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-05-14 19:09
|
||||
*/
|
||||
public class SQLColumn extends IColumn {
|
||||
|
||||
public static final SQLColumn PRIMARY_KEY_ID = new SQLColumn(SQLColumnType.INT, "id", SQLColumnOption.NOTNULL, SQLColumnOption.PRIMARY_KEY, SQLColumnOption.AUTO_INCREMENT);
|
||||
|
||||
private SQLColumnType columnType;
|
||||
private int m;
|
||||
private int d;
|
||||
|
||||
private String columnName;
|
||||
private Object defaultValue;
|
||||
|
||||
private SQLColumnOption[] columnOptions;
|
||||
|
||||
/**
|
||||
* 文本 类型常用构造器
|
||||
* new SQLColumn(SQLColumnType.TEXT, "username");
|
||||
*/
|
||||
public SQLColumn(SQLColumnType columnType, String columnName) {
|
||||
this(columnType, 0, 0, columnName, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* CHAR 类型常用构造器
|
||||
* new SQLColumn(SQLColumnType.CHAR, 1, "data");
|
||||
*/
|
||||
public SQLColumn(SQLColumnType columnType, int m, String columnName) {
|
||||
this(columnType, m, 0, columnName, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 主键 类型常用构造器
|
||||
* new SQLColumn(SQLColumnType.TEXT, "username", SQLColumnOption.PRIMARY_KEY, SQLColumnOption.AUTO_INCREMENT);
|
||||
*/
|
||||
public SQLColumn(SQLColumnType columnType, String columnName, SQLColumnOption... columnOptions) {
|
||||
this(columnType, 0, 0, columnName, null, columnOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据 类型常用构造器
|
||||
* new SQLColumn(SQLColumnType.TEXT, "player_group", "PLAYER");
|
||||
*/
|
||||
public SQLColumn(SQLColumnType columnType, String columnName, Object defaultValue) {
|
||||
this(columnType, 0, 0, columnName, defaultValue);
|
||||
}
|
||||
|
||||
public SQLColumn(SQLColumnType columnType, String columnName, Object defaultValue, SQLColumnOption... columnOptions) {
|
||||
this(columnType, 0, 0, columnName, defaultValue, columnOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* 完整构造器
|
||||
*
|
||||
* @param columnType 类型
|
||||
* @param m m值
|
||||
* @param d d值
|
||||
* @param columnName 名称
|
||||
* @param defaultValue 默认值
|
||||
* @param columnOptions 属性值
|
||||
*/
|
||||
public SQLColumn(SQLColumnType columnType, int m, int d, String columnName, Object defaultValue, SQLColumnOption... columnOptions) {
|
||||
this.columnType = columnType;
|
||||
this.m = m;
|
||||
this.d = d;
|
||||
this.columnName = columnName;
|
||||
this.defaultValue = defaultValue;
|
||||
this.columnOptions = columnOptions;
|
||||
}
|
||||
|
||||
public SQLColumn m(int m) {
|
||||
this.m = m;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SQLColumn d(int d) {
|
||||
this.d = d;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SQLColumn defaultValue(Object defaultValue) {
|
||||
this.defaultValue = defaultValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SQLColumn columnOptions(SQLColumnOption... columnOptions) {
|
||||
this.columnOptions = columnOptions;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String convertToCommand() {
|
||||
if (this.m == 0 && this.d == 0) {
|
||||
return Strings.replaceWithOrder("`{0}` {1}{2}", columnName, columnType.name().toLowerCase(), convertToOptions());
|
||||
} else if (this.d == 0) {
|
||||
return Strings.replaceWithOrder("`{0}` {1}({2}){3}", columnName, columnType.name().toLowerCase(), m, convertToOptions());
|
||||
} else {
|
||||
return Strings.replaceWithOrder("`{0}` {1}({2},{3}){4}", columnName, columnType.name().toLowerCase(), m, d, convertToOptions());
|
||||
}
|
||||
}
|
||||
|
||||
private String convertToOptions() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
Arrays.stream(columnOptions).forEach(option -> builder.append(" ").append(option.getText()));
|
||||
if (defaultValue != null) {
|
||||
if (defaultValue instanceof String) {
|
||||
builder.append(" DEFAULT '").append(defaultValue).append("'");
|
||||
} else {
|
||||
builder.append(" DEFAULT ").append(defaultValue);
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SQLColumn{" +
|
||||
"columnType=" + columnType +
|
||||
", m=" + m +
|
||||
", d=" + d +
|
||||
", columnName='" + columnName + '\'' +
|
||||
", defaultValue=" + defaultValue +
|
||||
", columnOptions=" + Arrays.toString(columnOptions) +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package io.izzel.taboolib.module.mysql.builder;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-05-14 21:43
|
||||
*/
|
||||
public enum SQLColumnOption {
|
||||
|
||||
/**
|
||||
* 不能为空
|
||||
*/
|
||||
NOTNULL("NOT NULL"),
|
||||
|
||||
/**
|
||||
* 唯一
|
||||
*/
|
||||
UNIQUE_KEY("UNIQUE KEY"),
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
PRIMARY_KEY("PRIMARY KEY"),
|
||||
|
||||
/**
|
||||
* 递增
|
||||
*/
|
||||
AUTO_INCREMENT("AUTO_INCREMENT");
|
||||
|
||||
String text;
|
||||
|
||||
SQLColumnOption(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
package io.izzel.taboolib.module.mysql.builder;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-05-14 19:13
|
||||
*/
|
||||
public enum SQLColumnType {
|
||||
|
||||
/**
|
||||
* 有符号值:-128 到127(- 27 到27 - 1)
|
||||
* 无符号值:0到255(0 到28 - 1) 1个字节
|
||||
*/
|
||||
TINYINT,
|
||||
|
||||
/**
|
||||
* 有符号值:-32768 到32767(- 215 到215 - 1)
|
||||
* 无符号值:0到65535(0 到21 6 - 1) 2个字节
|
||||
*/
|
||||
SMALLINT,
|
||||
|
||||
/**
|
||||
* 有符号值:-8388608 到8388607(- 22 3 到22 3 - 1 )
|
||||
* 无符号值:0到16777215(0 到22 4 - 1) 3个字节
|
||||
*/
|
||||
MEDIUMINT,
|
||||
|
||||
/**
|
||||
* 有符号值:-2147683648 到2147683647(- 231 到231- 1)
|
||||
* 无符号值:0到4294967295(0 到232 - 1) 4个字节
|
||||
*/
|
||||
INT,
|
||||
|
||||
/**
|
||||
* 有符号值:-9223372036854775808 到9223373036854775807(- 263到263-1)
|
||||
* 无符号值:0到18446744073709551615(0到264 – 1) 8个字节
|
||||
*/
|
||||
BIGINT,
|
||||
|
||||
/**
|
||||
* 最小非零值:±1.175494351e - 38
|
||||
*/
|
||||
FLOAT,
|
||||
|
||||
/**
|
||||
* 最小非零值:±2.2250738585072014e - 308
|
||||
*/
|
||||
DOUBLE,
|
||||
|
||||
/**
|
||||
* 可变:其值的范围依赖于m 和d
|
||||
*/
|
||||
DECIMAL,
|
||||
|
||||
/**
|
||||
* 定长:磁盘空间比较浪费,但是效率高,确定数据长度都一样,就使用定长
|
||||
* 比如:电话号码,身份证号
|
||||
* 最长可取255
|
||||
*/
|
||||
CHAR,
|
||||
|
||||
/**
|
||||
* 边长:比较节省空间,但是效率低,数据不能确定长度(不同数据长度有变化)
|
||||
* 比如:地址
|
||||
* 最长可取65535
|
||||
*/
|
||||
VARCHAR,
|
||||
|
||||
/**
|
||||
* 0~255字节值的长度+2字节
|
||||
*/
|
||||
TINYTEXT,
|
||||
|
||||
/**
|
||||
* 0~65535字节值的长度+2字节
|
||||
*/
|
||||
TEXT,
|
||||
|
||||
/**
|
||||
* 0~167772150字节值的长度+3字节
|
||||
*/
|
||||
MEDIUMTEXT,
|
||||
|
||||
/**
|
||||
* 0~4294967295字节值的长度+4字节
|
||||
*/
|
||||
LONGTEXT,
|
||||
|
||||
/**
|
||||
* 字节数为M,允许长度为0~M的定长二进制字符串
|
||||
*/
|
||||
BINARY,
|
||||
|
||||
/**
|
||||
* 允许长度为0~M的变长二进制字符串,字节数为值的长度加1
|
||||
*/
|
||||
VARBINARY,
|
||||
|
||||
/**
|
||||
* M位二进制数据,M最大值为64
|
||||
*/
|
||||
BIT,
|
||||
|
||||
/**
|
||||
* 可变长二进制数据,最多255个字节
|
||||
*/
|
||||
TINYBLOB,
|
||||
|
||||
/**
|
||||
* 可变长二进制数据,最多2的16次方-1个字节
|
||||
*/
|
||||
BLOB,
|
||||
|
||||
/**
|
||||
* 可变长二进制数据,最多2的24次方-1个字节
|
||||
*/
|
||||
MEDIUMBLOB,
|
||||
|
||||
/**
|
||||
* 可变长二进制数据,最多2的32次方-1个字节
|
||||
*/
|
||||
LONGBLOB
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package io.izzel.taboolib.module.mysql.builder;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-06-22 16:38
|
||||
*/
|
||||
public class SQLExecutor {
|
||||
|
||||
public static void freeConnection(Connection connection) {
|
||||
try {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
public static void freeStatement(PreparedStatement preparedStatement, ResultSet resultSet) {
|
||||
try {
|
||||
if (preparedStatement != null) {
|
||||
preparedStatement.close();
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
try {
|
||||
if (resultSet != null) {
|
||||
resultSet.close();
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
package io.izzel.taboolib.module.mysql.builder;
|
||||
|
||||
import io.izzel.taboolib.module.mysql.IHost;
|
||||
import io.izzel.taboolib.util.Strings;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-05-14 19:01
|
||||
*/
|
||||
public class SQLHost extends IHost {
|
||||
|
||||
private String host;
|
||||
private String user;
|
||||
private String port;
|
||||
private String password;
|
||||
private String database;
|
||||
private List<String> flags = Arrays.asList("characterEncoding=utf-8", "useSSL=false");
|
||||
|
||||
public SQLHost(ConfigurationSection section, Plugin plugin) {
|
||||
this(section, plugin, false);
|
||||
}
|
||||
|
||||
public SQLHost(ConfigurationSection section, Plugin plugin, boolean autoClose) {
|
||||
this(section.getString("host", "localhost"), section.getString("user", "root"), section.getString("port", "3306"), section.getString("password", ""), section.getString("database", "test"), plugin);
|
||||
}
|
||||
|
||||
public SQLHost(String host, int port, String user, String password, String database, Plugin plugin) {
|
||||
this(host, user, String.valueOf(port), password, database, plugin, false);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public SQLHost(String host, String user, String port, String password, String database, Plugin plugin) {
|
||||
this(host, user, port, password, database, plugin, false);
|
||||
}
|
||||
|
||||
public SQLHost(String host, String user, String port, String password, String database, Plugin plugin, boolean autoClose) {
|
||||
super(plugin, autoClose);
|
||||
this.host = host;
|
||||
this.user = user;
|
||||
this.port = port;
|
||||
this.password = password;
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConnectionUrl() {
|
||||
return Strings.replaceWithOrder("jdbc:mysql://{0}:{1}/{2}" + getFlagsInUrl(), this.host, this.port, this.database);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConnectionUrlSimple() {
|
||||
return Strings.replaceWithOrder("jdbc:mysql://{0}:{1}/{2}", this.host, this.port, this.database);
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public String getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public String getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public String getDatabase() {
|
||||
return database;
|
||||
}
|
||||
|
||||
public List<String> getFlags() {
|
||||
return flags;
|
||||
}
|
||||
|
||||
public String getFlagsInUrl() {
|
||||
if (flags.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
String collect = flags.stream().map(f -> f + "&").collect(Collectors.joining());
|
||||
return "?" + collect.substring(0, collect.length() - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof SQLHost)) {
|
||||
return false;
|
||||
}
|
||||
SQLHost sqlHost = (SQLHost) o;
|
||||
return Objects.equals(getHost(), sqlHost.getHost()) &&
|
||||
Objects.equals(getUser(), sqlHost.getUser()) &&
|
||||
Objects.equals(getPort(), sqlHost.getPort()) &&
|
||||
Objects.equals(getPassword(), sqlHost.getPassword()) &&
|
||||
Objects.equals(getDatabase(), sqlHost.getDatabase()) &&
|
||||
Objects.equals(getFlags(), sqlHost.getFlags());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getHost(), getUser(), getPort(), getPassword(), getDatabase(), getFlags());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SQLHost{" +
|
||||
"host='" + host + '\'' +
|
||||
", user='" + user + '\'' +
|
||||
", port='" + port + '\'' +
|
||||
", password='" + password + '\'' +
|
||||
", database='" + database + '\'' +
|
||||
", flags=" + flags +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package io.izzel.taboolib.module.mysql.builder;
|
||||
|
||||
import io.izzel.taboolib.module.mysql.IColumn;
|
||||
import io.izzel.taboolib.module.mysql.builder.query.RunnableQuery;
|
||||
import io.izzel.taboolib.module.mysql.builder.query.RunnableUpdate;
|
||||
import io.izzel.taboolib.util.ArrayUtil;
|
||||
import io.izzel.taboolib.util.Strings;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-05-14 19:07
|
||||
*/
|
||||
public class SQLTable {
|
||||
|
||||
private String tableName;
|
||||
private IColumn[] columns;
|
||||
|
||||
public SQLTable(String tableName) {
|
||||
this.tableName = tableName;
|
||||
}
|
||||
|
||||
public SQLTable(String tableName, IColumn... column) {
|
||||
this.tableName = tableName;
|
||||
this.columns = column;
|
||||
}
|
||||
|
||||
public SQLTable(String tableName, SQLColumn... column) {
|
||||
this.tableName = tableName;
|
||||
this.columns = column;
|
||||
}
|
||||
|
||||
public SQLTable column(IColumn column) {
|
||||
columns = columns == null ? new IColumn[] {column} : ArrayUtil.arrayAppend(columns, column);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public SQLTable addColumn(SQLColumn sqlColumn) {
|
||||
columns = columns == null ? new SQLColumn[] {sqlColumn} : ArrayUtil.arrayAppend(columns, sqlColumn);
|
||||
return this;
|
||||
}
|
||||
|
||||
public String createQuery() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
java.util.Arrays.stream(columns).forEach(sqlColumn -> builder.append(sqlColumn.convertToCommand()).append(", "));
|
||||
return Strings.replaceWithOrder("create table if not exists `{0}` ({1})", tableName, builder.substring(0, builder.length() - 2));
|
||||
}
|
||||
|
||||
public String deleteQuery() {
|
||||
return Strings.replaceWithOrder("drop table if exists `{0}`", tableName);
|
||||
}
|
||||
|
||||
public String cleanQuery() {
|
||||
return Strings.replaceWithOrder("delete from `{0}`", tableName);
|
||||
}
|
||||
|
||||
public String truncateQuery() {
|
||||
return Strings.replaceWithOrder("truncate table `{0}`", tableName);
|
||||
}
|
||||
|
||||
public RunnableQuery executeQuery(String query) {
|
||||
return new RunnableQuery(query);
|
||||
}
|
||||
|
||||
public RunnableQuery executeSelect() {
|
||||
return executeQuery("select * from " + tableName);
|
||||
}
|
||||
|
||||
public RunnableQuery executeSelect(String queryWhere) {
|
||||
return executeQuery("select * from " + tableName + " where " + queryWhere);
|
||||
}
|
||||
|
||||
public RunnableUpdate executeInsert(String queryValues) {
|
||||
return executeUpdate("insert into " + tableName + " values(" + queryValues + ")");
|
||||
}
|
||||
|
||||
public RunnableUpdate executeUpdate(String query) {
|
||||
return new RunnableUpdate(query);
|
||||
}
|
||||
|
||||
public RunnableUpdate executeUpdate(String update, String where) {
|
||||
return executeUpdate("update " + tableName + " set " + update + " where " + where);
|
||||
}
|
||||
|
||||
// *********************************
|
||||
//
|
||||
// Getter and Setter
|
||||
//
|
||||
// *********************************
|
||||
|
||||
public String getTableName() {
|
||||
return tableName;
|
||||
}
|
||||
|
||||
public IColumn[] getColumns() {
|
||||
return columns;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package io.izzel.taboolib.module.mysql.builder.query;
|
||||
|
||||
import io.izzel.taboolib.module.logger.TLogger;
|
||||
import io.izzel.taboolib.module.mysql.builder.SQLExecutor;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-07-03 21:29
|
||||
*/
|
||||
public class RunnableQuery {
|
||||
|
||||
private DataSource dataSource;
|
||||
private TaskStatement statement;
|
||||
private TaskResult result;
|
||||
private TaskResult resultNext;
|
||||
private TaskResult resultAutoNext;
|
||||
private Connection connection;
|
||||
private boolean autoClose;
|
||||
private String query;
|
||||
|
||||
public RunnableQuery(String query) {
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
public RunnableQuery dataSource(DataSource dataSource) {
|
||||
this.dataSource = dataSource;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RunnableQuery statement(TaskStatement statement) {
|
||||
this.statement = statement;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RunnableQuery result(TaskResult result) {
|
||||
this.result = result;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RunnableQuery resultNext(TaskResult result) {
|
||||
this.resultNext = result;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RunnableQuery resultAutoNext(TaskResult result) {
|
||||
this.resultAutoNext = result;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RunnableQuery connection(Connection connection) {
|
||||
return connection(connection, false);
|
||||
}
|
||||
|
||||
public RunnableQuery connection(Connection connection, boolean autoClose) {
|
||||
this.connection = connection;
|
||||
this.autoClose = autoClose;
|
||||
return this;
|
||||
}
|
||||
|
||||
public <T> T run(Object def, T translate) {
|
||||
Object object = run(def);
|
||||
return object == null ? def == null ? null : (T) def : (T) object;
|
||||
}
|
||||
|
||||
public Object run() {
|
||||
return run(null);
|
||||
}
|
||||
|
||||
public Object run(Object def) {
|
||||
PreparedStatement preparedStatement = null;
|
||||
ResultSet resultSet = null;
|
||||
if (dataSource != null) {
|
||||
try (Connection connection = dataSource.getConnection()) {
|
||||
preparedStatement = connection.prepareStatement(query);
|
||||
if (statement != null) {
|
||||
statement.execute(preparedStatement);
|
||||
}
|
||||
resultSet = preparedStatement.executeQuery();
|
||||
return getResult(resultSet);
|
||||
} catch (Exception e) {
|
||||
printException(e);
|
||||
} finally {
|
||||
SQLExecutor.freeStatement(preparedStatement, resultSet);
|
||||
}
|
||||
} else if (connection != null) {
|
||||
try {
|
||||
preparedStatement = connection.prepareStatement(query);
|
||||
if (statement != null) {
|
||||
statement.execute(preparedStatement);
|
||||
}
|
||||
resultSet = preparedStatement.executeQuery();
|
||||
return getResult(resultSet);
|
||||
} catch (Exception e) {
|
||||
printException(e);
|
||||
} finally {
|
||||
SQLExecutor.freeStatement(preparedStatement, resultSet);
|
||||
if (autoClose) {
|
||||
SQLExecutor.freeConnection(connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
private void printException(Exception e) {
|
||||
TLogger.getGlobalLogger().error("An exception occurred in the database. (" + query + ")");
|
||||
TLogger.getGlobalLogger().error("Reason: " + e.toString());
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
private Object getResult(ResultSet resultSet) throws SQLException {
|
||||
if (resultNext != null && resultSet.next()) {
|
||||
return resultNext.execute(resultSet);
|
||||
} else if (result != null) {
|
||||
return result.execute(resultSet);
|
||||
} else if (resultAutoNext != null) {
|
||||
Object result = null;
|
||||
while (resultSet.next()) {
|
||||
result = resultAutoNext.execute(resultSet);
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package io.izzel.taboolib.module.mysql.builder.query;
|
||||
|
||||
import io.izzel.taboolib.module.logger.TLogger;
|
||||
import io.izzel.taboolib.module.mysql.builder.SQLExecutor;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
|
||||
/**
|
||||
* F
|
||||
*
|
||||
* @Author sky
|
||||
* @Since 2018-07-03 21:29
|
||||
*/
|
||||
public class RunnableUpdate {
|
||||
|
||||
private DataSource dataSource;
|
||||
private TaskStatement statement;
|
||||
private Connection connection;
|
||||
private boolean autoClose;
|
||||
private String query;
|
||||
|
||||
public RunnableUpdate(String query) {
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
public RunnableUpdate dataSource(DataSource dataSource) {
|
||||
this.dataSource = dataSource;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RunnableUpdate statement(TaskStatement task) {
|
||||
this.statement = task;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RunnableUpdate connection(Connection connection) {
|
||||
return connection(connection, false);
|
||||
}
|
||||
|
||||
public RunnableUpdate connection(Connection connection, boolean autoClose) {
|
||||
this.connection = connection;
|
||||
this.autoClose = autoClose;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
PreparedStatement preparedStatement = null;
|
||||
if (dataSource != null) {
|
||||
try (Connection connection = dataSource.getConnection()) {
|
||||
preparedStatement = connection.prepareStatement(query);
|
||||
if (statement != null) {
|
||||
statement.execute(preparedStatement);
|
||||
}
|
||||
preparedStatement.executeUpdate();
|
||||
} catch (Exception e) {
|
||||
printException(e);
|
||||
} finally {
|
||||
SQLExecutor.freeStatement(preparedStatement, null);
|
||||
}
|
||||
} else if (connection != null) {
|
||||
try {
|
||||
preparedStatement = connection.prepareStatement(query);
|
||||
if (statement != null) {
|
||||
statement.execute(preparedStatement);
|
||||
}
|
||||
preparedStatement.executeUpdate();
|
||||
} catch (Exception e) {
|
||||
printException(e);
|
||||
} finally {
|
||||
SQLExecutor.freeStatement(preparedStatement, null);
|
||||
if (autoClose) {
|
||||
SQLExecutor.freeConnection(connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void printException(Exception e) {
|
||||
TLogger.getGlobalLogger().error("An exception occurred in the database. (" + query + ")");
|
||||
TLogger.getGlobalLogger().error("Reason: " + e.toString());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package io.izzel.taboolib.module.mysql.builder.query;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-07-03 22:02
|
||||
*/
|
||||
public interface TaskResult {
|
||||
|
||||
Object execute(ResultSet resultSet) throws SQLException;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package io.izzel.taboolib.module.mysql.builder.query;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-07-03 22:02
|
||||
*/
|
||||
public interface TaskStatement {
|
||||
|
||||
void execute(PreparedStatement preparedStatement) throws SQLException;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package io.izzel.taboolib.module.mysql.hikari;
|
||||
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import io.izzel.taboolib.locale.TLocale;
|
||||
import io.izzel.taboolib.module.config.TConfig;
|
||||
import io.izzel.taboolib.module.inject.TInject;
|
||||
import io.izzel.taboolib.module.mysql.IHost;
|
||||
import io.izzel.taboolib.module.mysql.builder.SQLHost;
|
||||
import io.izzel.taboolib.module.mysql.lite.SQLiteHost;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-05-16 21:59
|
||||
*/
|
||||
public class HikariHandler {
|
||||
|
||||
@TInject("datasource.yml")
|
||||
private static TConfig settings;
|
||||
private static ConcurrentHashMap<IHost, MapDataSource> dataSource = new ConcurrentHashMap<>();
|
||||
|
||||
public static DataSource createDataSource(IHost host) {
|
||||
return createDataSource(host, null);
|
||||
}
|
||||
|
||||
public static HikariDataSource createDataSource(IHost host, HikariConfig hikariConfig) {
|
||||
MapDataSource mapDataSource = dataSource.computeIfAbsent(host, x -> new MapDataSource(x, new HikariDataSource(hikariConfig == null ? createConfig(host) : hikariConfig)));
|
||||
mapDataSource.getActivePlugin().getAndIncrement();
|
||||
if (mapDataSource.getActivePlugin().get() == 1) {
|
||||
TLocale.Logger.info("MYSQL-HIKARI.CREATE-SUCCESS", host.getPlugin().getName(), host.getConnectionUrlSimple());
|
||||
} else {
|
||||
TLocale.Logger.info("MYSQL-HIKARI.CREATE-EXISTS", host.getPlugin().getName(), mapDataSource.getHost().getPlugin().getName());
|
||||
}
|
||||
return mapDataSource.getHikariDataSource();
|
||||
}
|
||||
|
||||
public static void closeDataSourceForce() {
|
||||
dataSource.values().forEach(x -> x.getHikariDataSource().close());
|
||||
}
|
||||
|
||||
public static void closeDataSource(IHost host) {
|
||||
if (host != null && dataSource.containsKey(host)) {
|
||||
MapDataSource mapDataSource = dataSource.get(host);
|
||||
if (mapDataSource.getActivePlugin().getAndDecrement() <= 1) {
|
||||
mapDataSource.getHikariDataSource().close();
|
||||
dataSource.remove(host);
|
||||
TLocale.Logger.info("MYSQL-HIKARI.CLOSE-SUCCESS", host.getPlugin().getName(), host.getConnectionUrlSimple());
|
||||
} else {
|
||||
TLocale.Logger.info("MYSQL-HIKARI.CLOSE-FAIL", host.getPlugin().getName(), String.valueOf(mapDataSource.getActivePlugin().get()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static HikariConfig createConfig(IHost host) {
|
||||
HikariConfig config = new HikariConfig();
|
||||
config.setJdbcUrl(host.getConnectionUrl());
|
||||
if (host instanceof SQLHost) {
|
||||
config.setDriverClassName(settings.getString("DefaultSettings.DriverClassName", "com.mysql.jdbc.Driver"));
|
||||
config.setUsername(((SQLHost) host).getUser());
|
||||
config.setPassword(((SQLHost) host).getPassword());
|
||||
} else if (host instanceof SQLiteHost) {
|
||||
config.setDriverClassName("org.sqlite.JDBC");
|
||||
} else {
|
||||
throw new IllegalArgumentException("Invalid host: " + host.getClass().getName());
|
||||
}
|
||||
config.setAutoCommit(settings.getBoolean("DefaultSettings.AutoCommit", true));
|
||||
config.setMinimumIdle(settings.getInt("DefaultSettings.MinimumIdle", 1));
|
||||
config.setMaximumPoolSize(settings.getInt("DefaultSettings.MaximumPoolSize", 10));
|
||||
config.setValidationTimeout(settings.getInt("DefaultSettings.ValidationTimeout", 5000));
|
||||
config.setConnectionTimeout(settings.getInt("DefaultSettings.ConnectionTimeout", 30000));
|
||||
config.setIdleTimeout(settings.getInt("DefaultSettings.IdleTimeout", 600000));
|
||||
config.setMaxLifetime(settings.getInt("DefaultSettings.MaxLifetime", 1800000));
|
||||
if (settings.contains("DefaultSettings.ConnectionTestQuery")) {
|
||||
config.setConnectionTestQuery(settings.getString("DefaultSettings.ConnectionTestQuery"));
|
||||
}
|
||||
if (settings.contains("DefaultSettings.DataSourceProperty")) {
|
||||
settings.getConfigurationSection("DefaultSettings.DataSourceProperty").getKeys(false).forEach(key -> config.addDataSourceProperty(key, settings.getString("DefaultSettings.DataSourceProperty." + key)));
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
// *********************************
|
||||
//
|
||||
// Getter and Setter
|
||||
//
|
||||
// *********************************
|
||||
|
||||
public static ConcurrentHashMap<IHost, MapDataSource> getDataSource() {
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
public static FileConfiguration getSettings() {
|
||||
return settings;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package io.izzel.taboolib.module.mysql.hikari;
|
||||
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import io.izzel.taboolib.module.mysql.IHost;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-05-17 23:47
|
||||
*/
|
||||
public class MapDataSource {
|
||||
|
||||
private IHost host;
|
||||
private AtomicInteger activePlugin;
|
||||
private HikariDataSource hikariDataSource;
|
||||
|
||||
MapDataSource(IHost host, HikariDataSource hikariDataSource) {
|
||||
this.host = host;
|
||||
this.activePlugin = new AtomicInteger();
|
||||
this.hikariDataSource = hikariDataSource;
|
||||
}
|
||||
|
||||
public IHost getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public AtomicInteger getActivePlugin() {
|
||||
return activePlugin;
|
||||
}
|
||||
|
||||
public HikariDataSource getHikariDataSource() {
|
||||
return hikariDataSource;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
package io.izzel.taboolib.module.mysql.lite;
|
||||
|
||||
import io.izzel.taboolib.util.Strings;
|
||||
import io.izzel.taboolib.module.mysql.IColumn;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-05-14 19:09
|
||||
*/
|
||||
public class SQLiteColumn extends IColumn {
|
||||
|
||||
public static final SQLiteColumn PRIMARY_KEY_ID = new SQLiteColumn(SQLiteColumnType.INTEGER, "id", SQLiteColumnOption.NOTNULL, SQLiteColumnOption.PRIMARY_KEY, SQLiteColumnOption.AUTOINCREMENT);
|
||||
|
||||
private SQLiteColumnType columnType;
|
||||
private int m;
|
||||
private int d;
|
||||
|
||||
private String columnName;
|
||||
private Object defaultValue;
|
||||
|
||||
private SQLiteColumnOption[] columnOptions;
|
||||
|
||||
/**
|
||||
* 文本 类型常用构造器
|
||||
* new SQLColumn(SQLiteColumnType.TEXT, "username");
|
||||
*/
|
||||
public SQLiteColumn(SQLiteColumnType columnType, String columnName) {
|
||||
this(columnType, 0, 0, columnName, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 主键 类型常用构造器
|
||||
* new SQLColumn(SQLiteColumnType.TEXT, "username", SQLiteColumnOption.PRIMARY_KEY, SQLiteColumnOption.AUTO_INCREMENT);
|
||||
*/
|
||||
public SQLiteColumn(SQLiteColumnType columnType, String columnName, SQLiteColumnOption... columnOptions) {
|
||||
this(columnType, 0, 0, columnName, null, columnOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据 类型常用构造器
|
||||
* new SQLColumn(SQLiteColumnType.TEXT, "player_group", "PLAYER");
|
||||
*/
|
||||
public SQLiteColumn(SQLiteColumnType columnType, String columnName, Object defaultValue) {
|
||||
this(columnType, 0, 0, columnName, defaultValue);
|
||||
}
|
||||
|
||||
public SQLiteColumn(SQLiteColumnType columnType, String columnName, Object defaultValue, SQLiteColumnOption... columnOptions) {
|
||||
this(columnType, 0, 0, columnName, defaultValue, columnOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* 完整构造器
|
||||
*
|
||||
* @param columnType 类型
|
||||
* @param m m值
|
||||
* @param d d值
|
||||
* @param columnName 名称
|
||||
* @param defaultValue 默认值
|
||||
* @param columnOptions 属性值
|
||||
*/
|
||||
public SQLiteColumn(SQLiteColumnType columnType, int m, int d, String columnName, Object defaultValue, SQLiteColumnOption... columnOptions) {
|
||||
this.columnType = columnType;
|
||||
this.m = m;
|
||||
this.d = d;
|
||||
this.columnName = columnName;
|
||||
this.defaultValue = defaultValue;
|
||||
this.columnOptions = columnOptions;
|
||||
}
|
||||
|
||||
public SQLiteColumn m(int m) {
|
||||
this.m = m;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SQLiteColumn d(int d) {
|
||||
this.d = d;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SQLiteColumn defaultValue(Object defaultValue) {
|
||||
this.defaultValue = defaultValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SQLiteColumn columnOptions(SQLiteColumnOption... columnOptions) {
|
||||
this.columnOptions = columnOptions;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String convertToCommand() {
|
||||
if (this.m == 0 && this.d == 0) {
|
||||
return Strings.replaceWithOrder("`{0}` {1}{2}", columnName, columnType.name().toLowerCase(), convertToOptions());
|
||||
} else if (this.d == 0) {
|
||||
return Strings.replaceWithOrder("`{0}` {1}({2}){3}", columnName, columnType.name().toLowerCase(), m, convertToOptions());
|
||||
} else {
|
||||
return Strings.replaceWithOrder("`{0}` {1}({2},{3}){4}", columnName, columnType.name().toLowerCase(), m, d, convertToOptions());
|
||||
}
|
||||
}
|
||||
|
||||
private String convertToOptions() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
Arrays.stream(columnOptions).forEach(option -> builder.append(" ").append(option.getText()));
|
||||
if (defaultValue != null) {
|
||||
if (defaultValue instanceof String) {
|
||||
builder.append(" DEFAULT '").append(defaultValue).append("'");
|
||||
} else {
|
||||
builder.append(" DEFAULT ").append(defaultValue);
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SQLiteColumn{" +
|
||||
"columnType=" + columnType +
|
||||
", m=" + m +
|
||||
", d=" + d +
|
||||
", columnName='" + columnName + '\'' +
|
||||
", defaultValue=" + defaultValue +
|
||||
", columnOptions=" + Arrays.toString(columnOptions) +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package io.izzel.taboolib.module.mysql.lite;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-05-14 21:43
|
||||
*/
|
||||
public enum SQLiteColumnOption {
|
||||
|
||||
/**
|
||||
* 不能为空
|
||||
*/
|
||||
NOTNULL("NOT NULL"),
|
||||
|
||||
/**
|
||||
* 唯一
|
||||
*/
|
||||
UNIQUE("UNIQUE"),
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
PRIMARY_KEY("PRIMARY KEY"),
|
||||
|
||||
/**
|
||||
* 递增
|
||||
*/
|
||||
AUTOINCREMENT("AUTOINCREMENT");
|
||||
|
||||
String text;
|
||||
|
||||
SQLiteColumnOption(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user