diff --git a/src/main/java/me/skymc/taboolib/Main.java b/src/main/java/me/skymc/taboolib/Main.java index 17591d7..20f0dd5 100644 --- a/src/main/java/me/skymc/taboolib/Main.java +++ b/src/main/java/me/skymc/taboolib/Main.java @@ -39,6 +39,8 @@ import me.skymc.taboolib.string.StringUtils; import me.skymc.taboolib.string.language2.Language2; import me.skymc.taboolib.support.SupportPlaceholder; import me.skymc.taboolib.timecycle.TimeCycleManager; +import me.skymc.taboolib.translateuuid.TranslateUUID; +import me.skymc.taboolib.translateuuid.TranslateUUIDCommand; import me.skymc.taboolib.update.UpdateTask; import me.skymc.tlm.TLM; import me.skymc.tlm.command.TLMCommands; @@ -186,10 +188,12 @@ public class Main extends JavaPlugin implements Listener { new SupportPlaceholder(getInst(), "taboolib").hook(); } - // 载入 SpecialItem 接口 - SpecialItem.getInst().loadItems(); // 载入 TLM 接口 TLM.getInst(); + // 载入 SpecialItem 接口 + SpecialItem.getInst().loadItems(); + // 载入 TranslateUUID 工具 + TranslateUUID.init(); // 面子工程 InputStream inputStream = FileUtils.getResource("motd.txt"); @@ -236,6 +240,8 @@ public class Main extends JavaPlugin implements Listener { SpecialItem.getInst().unloadItems(); // 注销 TLM 接口 TabooLibraryModule.getInst().unloadModules(); + // 注销 TranslateUUID 接口 + TranslateUUID.cancel(); // 注销连接池 HikariHandler.closeDataSourceForce(); @@ -343,6 +349,7 @@ public class Main extends JavaPlugin implements Listener { TBaseCommand.registerCommand("taboolib", new TabooLibMainCommand()); TBaseCommand.registerCommand("tabooliblocale", new TabooLibLocaleCommand()); TBaseCommand.registerCommand("taboolibplugin", new TabooLibPluginMainCommand()); + TBaseCommand.registerCommand("translateuuid", new TranslateUUIDCommand()); } private void registerListener() { diff --git a/src/main/java/me/skymc/taboolib/commands/TabooLibMainCommand.java b/src/main/java/me/skymc/taboolib/commands/TabooLibMainCommand.java index be3b138..9b120a0 100644 --- a/src/main/java/me/skymc/taboolib/commands/TabooLibMainCommand.java +++ b/src/main/java/me/skymc/taboolib/commands/TabooLibMainCommand.java @@ -797,12 +797,6 @@ public class TabooLibMainCommand extends BaseMainCommand { return; } - File file = new File("plugins/update"); - if (!file.exists()) { - TLocale.sendTo(sender, "COMMANDS.TABOOLIB.UPDATEPLUGIN.UPDATE-NOT-SUPPORT"); - return; - } - File pluginFile = PluginUtils.getPluginFile(Main.getInst()); if (pluginFile == null) { TLocale.sendTo(sender, "COMMANDS.TABOOLIB.UPDATEPLUGIN.FILE-NOT-FOUND"); @@ -815,8 +809,15 @@ public class TabooLibMainCommand extends BaseMainCommand { public void run() { String url = Strings.replaceWithOrder("https://github.com/Bkm016/TabooLib/releases/download/{0}/TabooLib-{0}.jar", UpdateTask.getNewVersion()); TLocale.sendTo(sender, "COMMANDS.TABOOLIB.UPDATEPLUGIN.UPDATE-START", url); - FileUtils.download(url, new File(file, pluginFile.getName())); - TLocale.sendTo(sender, "COMMANDS.TABOOLIB.UPDATEPLUGIN.UPDATE-SUCCESS"); + + File file = new File("plugins/update"); + if (file.exists()) { + FileUtils.download(url, new File(file, pluginFile.getName())); + TLocale.sendTo(sender, "COMMANDS.TABOOLIB.UPDATEPLUGIN.UPDATE-SUCCESS"); + } else { + FileUtils.download(url, pluginFile); + Bukkit.shutdown(); + } } }.runTaskAsynchronously(Main.getInst()); } diff --git a/src/main/java/me/skymc/taboolib/csvutils/CsvReader.java b/src/main/java/me/skymc/taboolib/csvutils/CsvReader.java index fda2878..cfc3477 100644 --- a/src/main/java/me/skymc/taboolib/csvutils/CsvReader.java +++ b/src/main/java/me/skymc/taboolib/csvutils/CsvReader.java @@ -500,7 +500,7 @@ public class CsvReader { ++dataBuffer2.Position; if (this.userSettings.SafetySwitch && this.dataBuffer.Position - this.dataBuffer.ColumnStart + this.columnBuffer.Position > 100000) { this.close(); - throw new IOException("Maximum column length of 100,000 exceeded in column " + NumberFormat.getIntegerInstance().format(this.columnsCount) + " in record " + NumberFormat.getIntegerInstance().format(this.currentRecord) + ". Set the SafetySwitch property to false" + " if you're expecting column lengths greater than 100,000 characters to" + " avoid this error."); + throw new IOException("Maximum addColumn length of 100,000 exceeded in addColumn " + NumberFormat.getIntegerInstance().format(this.columnsCount) + " in record " + NumberFormat.getIntegerInstance().format(this.currentRecord) + ". Set the SafetySwitch property to false" + " if you're expecting addColumn lengths greater than 100,000 characters to" + " avoid this error."); } } } while (this.hasMoreData && this.startedColumn); @@ -695,7 +695,7 @@ public class CsvReader { ++dataBuffer3.Position; if (this.userSettings.SafetySwitch && this.dataBuffer.Position - this.dataBuffer.ColumnStart + this.columnBuffer.Position > 100000) { this.close(); - throw new IOException("Maximum column length of 100,000 exceeded in column " + NumberFormat.getIntegerInstance().format(this.columnsCount) + " in record " + NumberFormat.getIntegerInstance().format(this.currentRecord) + ". Set the SafetySwitch property to false" + " if you're expecting column lengths greater than 100,000 characters to" + " avoid this error."); + throw new IOException("Maximum addColumn length of 100,000 exceeded in addColumn " + NumberFormat.getIntegerInstance().format(this.columnsCount) + " in record " + NumberFormat.getIntegerInstance().format(this.currentRecord) + ". Set the SafetySwitch property to false" + " if you're expecting addColumn lengths greater than 100,000 characters to" + " avoid this error."); } } } while (this.hasMoreData && this.startedColumn); @@ -868,7 +868,7 @@ public class CsvReader { this.startedColumn = false; if (this.columnsCount >= 100000 && this.userSettings.SafetySwitch) { this.close(); - throw new IOException("Maximum column count of 100,000 exceeded in record " + NumberFormat.getIntegerInstance().format(this.currentRecord) + ". Set the SafetySwitch property to false" + " if you're expecting more than 100,000 columns per record to" + " avoid this error."); + throw new IOException("Maximum addColumn count of 100,000 exceeded in record " + NumberFormat.getIntegerInstance().format(this.currentRecord) + ". Set the SafetySwitch property to false" + " if you're expecting more than 100,000 columns per record to" + " avoid this error."); } if (this.columnsCount == this.values.length) { final int n3 = this.values.length * 2; diff --git a/src/main/java/me/skymc/taboolib/inventory/speciaitem/SpecialItem.java b/src/main/java/me/skymc/taboolib/inventory/speciaitem/SpecialItem.java index 77950b3..6a5c9c8 100644 --- a/src/main/java/me/skymc/taboolib/inventory/speciaitem/SpecialItem.java +++ b/src/main/java/me/skymc/taboolib/inventory/speciaitem/SpecialItem.java @@ -176,6 +176,7 @@ public class SpecialItem implements Listener { e.getWhoClicked().setItemOnCursor(null); } break; + default: } } } diff --git a/src/main/java/me/skymc/taboolib/javashell/utils/JarUtils.java b/src/main/java/me/skymc/taboolib/javashell/utils/JarUtils.java index 804bd71..97dafac 100644 --- a/src/main/java/me/skymc/taboolib/javashell/utils/JarUtils.java +++ b/src/main/java/me/skymc/taboolib/javashell/utils/JarUtils.java @@ -14,86 +14,87 @@ import java.util.jar.JarFile; public class JarUtils { - public static boolean extractFromJar(final String fileName, final String dest) throws IOException { - if (getRunningJar() == null) { - return false; - } - final File file = new File(dest); - if (file.isDirectory()) { - file.mkdir(); - return false; - } - if (!file.exists()) { - file.getParentFile().mkdirs(); - } + public static boolean extractFromJar(final String fileName, final String dest) throws IOException { + if (getRunningJar() == null) { + return false; + } + final File file = new File(dest); + if (file.isDirectory()) { + file.mkdir(); + return false; + } + if (!file.exists()) { + file.getParentFile().mkdirs(); + } - final JarFile jar = getRunningJar(); - final Enumeration e = jar.entries(); - while (e.hasMoreElements()) { - final JarEntry je = e.nextElement(); - if (!je.getName().contains(fileName)) { - continue; - } - final InputStream in = new BufferedInputStream(jar.getInputStream(je)); - final OutputStream out = new BufferedOutputStream(new FileOutputStream(file)); - copyInputStream(in, out); - jar.close(); - return true; - } - jar.close(); - return false; - } + final JarFile jar = getRunningJar(); + final Enumeration e = jar.entries(); + while (e.hasMoreElements()) { + final JarEntry je = e.nextElement(); + if (!je.getName().contains(fileName)) { + continue; + } + final InputStream in = new BufferedInputStream(jar.getInputStream(je)); + final OutputStream out = new BufferedOutputStream(new FileOutputStream(file)); + copyInputStream(in, out); + jar.close(); + return true; + } + jar.close(); + return false; + } private static void copyInputStream(final InputStream in, final OutputStream out) throws IOException { - try { - final byte[] buff = new byte[4096]; - int n; - while ((n = in.read(buff)) > 0) { - out.write(buff, 0, n); - } - } finally { - out.flush(); - out.close(); - in.close(); - } - } + try { + final byte[] buff = new byte[4096]; + int n; + while ((n = in.read(buff)) > 0) { + out.write(buff, 0, n); + } + } finally { + out.flush(); + out.close(); + in.close(); + } + } - @Deprecated - public static URL getJarUrl(final File file) throws IOException { - return new URL("jar:" + file.toURI().toURL().toExternalForm() + "!/"); - } + @Deprecated + public static URL getJarUrl(final File file) throws IOException { + return new URL("jar:" + file.toURI().toURL().toExternalForm() + "!/"); + } - public static JarFile getRunningJar() throws IOException { - if (!RUNNING_FROM_JAR) { - return null; // null if not running from jar - } - String path = new File(JarUtils.class.getProtectionDomain().getCodeSource().getLocation().getPath()) - .getAbsolutePath(); - path = URLDecoder.decode(path, "UTF-8"); - return new JarFile(path); - } + public static JarFile getRunningJar() throws IOException { + if (!RUNNING_FROM_JAR) { + // null if not running from jar + return null; + } + String path = new File(JarUtils.class.getProtectionDomain().getCodeSource().getLocation().getPath()) + .getAbsolutePath(); + path = URLDecoder.decode(path, "UTF-8"); + return new JarFile(path); + } - private static boolean RUNNING_FROM_JAR = false; + private static boolean RUNNING_FROM_JAR = false; - static { - final URL resource = JarUtils.class.getClassLoader().getResource("plugin.yml"); - if (resource != null) { - RUNNING_FROM_JAR = true; - } - } + static { + final URL resource = JarUtils.class.getClassLoader().getResource("plugin.yml"); + if (resource != null) { + RUNNING_FROM_JAR = true; + } + } - @Deprecated - public static void addClassPath(final URL url) { - final URLClassLoader sysloader = (URLClassLoader) Bukkit.class.getClassLoader(); - final Class sysclass = URLClassLoader.class; - try { - final Method method = sysclass.getDeclaredMethod("addURL", URL.class); - method.setAccessible(true); - method.invoke(sysloader, url); - } catch (Throwable t) { - MsgUtils.warn("无法添加添加 &4" + url + "&c 到运行库"); - MsgUtils.warn(t.getMessage()); - } - } + @Deprecated + public static void addClassPath(final URL url) { + final URLClassLoader sysloader = (URLClassLoader) Bukkit.class.getClassLoader(); + final Class sysclass = URLClassLoader.class; + try { + final Method method = sysclass.getDeclaredMethod("addURL", URL.class); + method.setAccessible(true); + method.invoke(sysloader, url); + } catch (Throwable t) { + MsgUtils.warn("无法添加添加 &4" + url + "&c 到运行库"); + MsgUtils.warn(t.getMessage()); + } + } } \ No newline at end of file diff --git a/src/main/java/me/skymc/taboolib/listener/ListenerPlayerJoinAndQuit.java b/src/main/java/me/skymc/taboolib/listener/ListenerPlayerJoinAndQuit.java index 3f262df..f166520 100644 --- a/src/main/java/me/skymc/taboolib/listener/ListenerPlayerJoinAndQuit.java +++ b/src/main/java/me/skymc/taboolib/listener/ListenerPlayerJoinAndQuit.java @@ -1,9 +1,12 @@ package me.skymc.taboolib.listener; import com.ilummc.tlib.resources.TLocale; +import me.skymc.taboolib.Main; import me.skymc.taboolib.TabooLib; import me.skymc.taboolib.playerdata.DataUtils; +import me.skymc.taboolib.translateuuid.TranslateUUID; import me.skymc.taboolib.update.UpdateTask; +import org.bukkit.Bukkit; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; @@ -17,6 +20,9 @@ public class ListenerPlayerJoinAndQuit implements Listener { if (UpdateTask.isHaveUpdate() && e.getPlayer().hasPermission("taboolib.update.notify")) { TLocale.Logger.sendTo(e.getPlayer(), "UPDATETASK.VERSION-OUTDATED", String.valueOf(TabooLib.getPluginVersion()), String.valueOf(UpdateTask.getNewVersion())); } + if (TranslateUUID.isEnabled()) { + Bukkit.getScheduler().runTaskAsynchronously(Main.getInst(), () -> TranslateUUID.updateUsername(e.getPlayer().getUniqueId(), e.getPlayer().getName())); + } } @EventHandler(priority = EventPriority.MONITOR) diff --git a/src/main/java/me/skymc/taboolib/mysql/builder/SQLColumn.java b/src/main/java/me/skymc/taboolib/mysql/builder/SQLColumn.java index c209065..cf7ce3f 100644 --- a/src/main/java/me/skymc/taboolib/mysql/builder/SQLColumn.java +++ b/src/main/java/me/skymc/taboolib/mysql/builder/SQLColumn.java @@ -10,26 +10,15 @@ import java.util.Arrays; */ public class SQLColumn { - /** - * 类型 - */ + 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; /** @@ -106,30 +95,32 @@ public class SQLColumn { } private String convertToOptions() { - StringBuilder stringBuilder = new StringBuilder(); + StringBuilder builder = new StringBuilder(); for (SQLColumnOption options : columnOptions) { switch (options) { case NOTNULL: - stringBuilder.append(" not null"); + builder.append(" not null"); break; case PRIMARY_KEY: - stringBuilder.append(" primary key"); + builder.append(" primary key"); break; case AUTO_INCREMENT: - stringBuilder.append(" auto_increment"); + builder.append(" auto_increment"); break; case UNIQUE_KEY: - stringBuilder.append(" unique key"); + builder.append(" unique key"); break; default: } } - if (defaultValue instanceof String) { - stringBuilder.append(" default '").append(defaultValue).append("'"); - } else { - stringBuilder.append(" default ").append(defaultValue); + if (defaultValue != null) { + if (defaultValue instanceof String) { + builder.append(" default '").append(defaultValue).append("'"); + } else { + builder.append(" default ").append(defaultValue); + } } - return stringBuilder.toString(); + return builder.toString(); } @Override diff --git a/src/main/java/me/skymc/taboolib/mysql/builder/SQLExecutor.java b/src/main/java/me/skymc/taboolib/mysql/builder/SQLExecutor.java new file mode 100644 index 0000000..a6846ab --- /dev/null +++ b/src/main/java/me/skymc/taboolib/mysql/builder/SQLExecutor.java @@ -0,0 +1,36 @@ +package me.skymc.taboolib.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) { + } + } +} diff --git a/src/main/java/me/skymc/taboolib/mysql/builder/SQLHost.java b/src/main/java/me/skymc/taboolib/mysql/builder/SQLHost.java index 718fc5a..185a59b 100644 --- a/src/main/java/me/skymc/taboolib/mysql/builder/SQLHost.java +++ b/src/main/java/me/skymc/taboolib/mysql/builder/SQLHost.java @@ -1,10 +1,10 @@ package me.skymc.taboolib.mysql.builder; -import com.ilummc.tlib.util.Ref; import com.ilummc.tlib.util.Strings; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.plugin.Plugin; +import java.text.MessageFormat; import java.util.Objects; /** @@ -84,6 +84,6 @@ public class SQLHost { @Override public String toString() { - return "host='" + "SQLHost{" + host + '\'' + ", user='" + user + '\'' + ", port='" + port + '\'' + ", password='" + password + '\'' + ", database='" + database + '\'' + '}'; + return MessageFormat.format("SQLHost'{'host=''{0}'', user=''{1}'', port=''{2}'', password=''{3}'', database=''{4}'', plugin={5}'}'", host, user, port, password, database, plugin); } } diff --git a/src/main/java/me/skymc/taboolib/mysql/builder/SQLTable.java b/src/main/java/me/skymc/taboolib/mysql/builder/SQLTable.java index 3c07bba..9e88b9f 100644 --- a/src/main/java/me/skymc/taboolib/mysql/builder/SQLTable.java +++ b/src/main/java/me/skymc/taboolib/mysql/builder/SQLTable.java @@ -1,19 +1,63 @@ package me.skymc.taboolib.mysql.builder; +import com.google.common.base.Preconditions; +import com.ilummc.tlib.util.Strings; +import me.skymc.taboolib.string.ArrayUtils; + /** * @Author sky * @Since 2018-05-14 19:07 */ public class SQLTable { - private final String tableName; - private final SQLColumn[] columns; + private String tableName; + private SQLColumn[] columns; - public SQLTable(String tableName, SQLColumn... columns) { + public SQLTable(String tableName) { this.tableName = tableName; - this.columns = columns; } + public SQLTable(String tableName, SQLColumn... column) { + this.tableName = tableName; + this.columns = column; + } + + public SQLTable addColumn(SQLColumn sqlColumn) { + if (columns == null) { + columns = new SQLColumn[]{sqlColumn}; + } else { + ArrayUtils.arrayAppend(columns, sqlColumn); + } + return this; + } + + public String createQuery() { + Preconditions.checkNotNull(columns); + StringBuilder builder = new StringBuilder(); + for (SQLColumn sqlColumn : columns) { + 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); + } + + // ********************************* + // + // Getter and Setter + // + // ********************************* + public String getTableName() { return tableName; } diff --git a/src/main/java/me/skymc/taboolib/mysql/hikari/HikariHandler.java b/src/main/java/me/skymc/taboolib/mysql/hikari/HikariHandler.java index 089d1ed..4a65e96 100644 --- a/src/main/java/me/skymc/taboolib/mysql/hikari/HikariHandler.java +++ b/src/main/java/me/skymc/taboolib/mysql/hikari/HikariHandler.java @@ -22,6 +22,7 @@ public class HikariHandler { * * @param host 数据库地址 * @return {@link HikariDataSource} + * @throws java.sql.SQLException 数据库连接失败异常 */ public static HikariDataSource createDataSource(SQLHost host, HikariConfig hikariConfig) { MapDataSource mapDataSource = dataSource.computeIfAbsent(host, x -> new MapDataSource(x, new HikariDataSource(hikariConfig == null ? createConfig(host) : hikariConfig))); @@ -50,7 +51,7 @@ public class HikariHandler { * @param host 地址 */ public static void closeDataSource(SQLHost host) { - if (dataSource.containsKey(host)) { + if (host != null && dataSource.containsKey(host)) { MapDataSource mapDataSource = dataSource.get(host); if (mapDataSource.getActivePlugin().getAndDecrement() <= 1) { mapDataSource.getHikariDataSource().close(); diff --git a/src/main/java/me/skymc/taboolib/translateuuid/TranslateUUID.java b/src/main/java/me/skymc/taboolib/translateuuid/TranslateUUID.java new file mode 100644 index 0000000..c32d170 --- /dev/null +++ b/src/main/java/me/skymc/taboolib/translateuuid/TranslateUUID.java @@ -0,0 +1,217 @@ +package me.skymc.taboolib.translateuuid; + +import com.ilummc.tlib.logger.TLogger; +import com.ilummc.tlib.util.Strings; +import com.zaxxer.hikari.HikariDataSource; +import me.skymc.taboolib.Main; +import me.skymc.taboolib.fileutils.ConfigUtils; +import me.skymc.taboolib.json.JSONObject; +import me.skymc.taboolib.mysql.builder.*; +import me.skymc.taboolib.mysql.hikari.HikariHandler; +import me.skymc.taboolib.nms.NMSUtils; +import org.bukkit.configuration.file.FileConfiguration; + +import java.io.*; +import java.lang.reflect.Method; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Properties; +import java.util.UUID; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @Author sky + * @Since 2018-06-21 22:16 + */ +public class TranslateUUID { + + private static FileConfiguration settings; + private static HikariDataSource dataSource; + + private static SQLHost sqlHost; + private static SQLTable sqlTable; + + private static final String INSERT_PLAYER_DATA = "insert into {0} values(null, ?, ?)"; + private static final String SELECT_WITH_UUID = "select * from {0} where uuid = ?"; + private static final String SELECT_WITH_USERNAME = "select * from {0} where username = ?"; + private static final String UPDATE_PLAYER_USERNAME = "update {0} set username = ? where uuid = ?"; + + private static boolean enabled = false; + + public static void init() { + settings = ConfigUtils.saveDefaultConfig(Main.getInst(), "translateuuid.yml"); + if (!settings.getBoolean("Enable")) { + enabled = false; + return; + } + sqlHost = new SQLHost(settings.getConfigurationSection("Database"), Main.getInst()); + sqlTable = new SQLTable(settings.getString("Database.table"), SQLColumn.PRIMARY_KEY_ID, new SQLColumn(SQLColumnType.TEXT, "uuid"), new SQLColumn(SQLColumnType.TEXT, "username")); + try { + dataSource = HikariHandler.createDataSource(sqlHost, null); + createTable(); + } catch (Exception e) { + TLogger.getGlobalLogger().error("Database connected fail: " + e.toString()); + } + enabled = true; + } + + public static void cancel() { + HikariHandler.closeDataSource(sqlHost); + } + + public static String translateUUID(String username) { + try (Connection connection = dataSource.getConnection()) { + return translateInternal(connection, username, "uuid", SELECT_WITH_USERNAME); + } catch (SQLException e) { + TLogger.getGlobalLogger().error("Database error: " + e.toString()); + return null; + } + } + + public static String translateUsername(UUID uuid) { + try (Connection connection = dataSource.getConnection()) { + return translateInternal(connection, uuid.toString(), "username", SELECT_WITH_UUID); + } catch (SQLException e) { + TLogger.getGlobalLogger().error("Database error: " + e.toString()); + return null; + } + } + + public static void updateUsername(UUID uuid, String username) { + PreparedStatement preparedStatement = null; + try (Connection connection = dataSource.getConnection()) { + String usernameExists = translateInternal(connection, uuid.toString(), "username", SELECT_WITH_UUID); + if (usernameExists == null) { + preparedStatement = connection.prepareStatement(Strings.replaceWithOrder(INSERT_PLAYER_DATA, sqlTable.getTableName())); + preparedStatement.setString(1, uuid.toString()); + preparedStatement.setString(2, username); + } else { + preparedStatement = connection.prepareStatement(Strings.replaceWithOrder(UPDATE_PLAYER_USERNAME, sqlTable.getTableName())); + preparedStatement.setString(1, username); + preparedStatement.setString(2, uuid.toString()); + } + preparedStatement.executeUpdate(); + } catch (SQLException e) { + TLogger.getGlobalLogger().error("Database error: " + e.toString()); + } finally { + SQLExecutor.freeStatement(preparedStatement, null); + } + } + + public static void importLocal() { + File worldFolder = new File(getDefaultWorldName()); + if (!worldFolder.exists()) { + TLogger.getGlobalLogger().error("Invalid \"world\" folder"); + return; + } + + File playerDataFolder = new File(worldFolder, "playerdata"); + if (!playerDataFolder.exists() || !playerDataFolder.isDirectory()) { + TLogger.getGlobalLogger().error("Invalid \"playerdata\" folder"); + return; + } + + ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(32); + + AtomicInteger i = new AtomicInteger(); + int size = playerDataFolder.listFiles().length; + + TLogger.getGlobalLogger().info("Start importing the local data..."); + for (File file : playerDataFolder.listFiles()) { + threadPool.submit(() -> { + try { + String username = getUsernameInDatFile(file); + updateUsername(UUID.fromString(file.getName().split("\\.")[0]), username); + TLogger.getGlobalLogger().info("importing... " + username + "(" + i.getAndIncrement() + "/" + size + ")"); + } catch (Exception ignored) { + } + }); + } + + threadPool.shutdown(); + } + + public static JSONObject getPlayerDataInDatFile(File datFile) { + Class clazz = NMSUtils.getNMSClassSilent("NBTCompressedStreamTools"); + try (FileInputStream fileInputStream = new FileInputStream(datFile)) { + Method a = clazz.getMethod("a", InputStream.class); + Object nbtTagCompound = a.invoke(null, fileInputStream); + return new JSONObject(nbtTagCompound.getClass().getMethod("toString").invoke(nbtTagCompound)); + } catch (Exception ignored) { + } + return new JSONObject(); + } + + // ********************************* + // + // Private Methods + // + // ********************************* + + private static void createTable() { + PreparedStatement preparedStatement = null; + try (Connection connection = dataSource.getConnection()) { + preparedStatement = connection.prepareStatement(sqlTable.createQuery()); + preparedStatement.executeUpdate(); + } catch (SQLException e) { + TLogger.getGlobalLogger().error("Database error: " + e.toString()); + } finally { + SQLExecutor.freeStatement(preparedStatement, null); + } + } + + private static String getDefaultWorldName() { + Properties properties = new Properties(); + try { + properties.load(new FileReader(new File("server.properties"))); + } catch (IOException ignored) { + } + return properties.getProperty("level-name", "world"); + } + + private static String getUsernameInDatFile(File datFile) { + Class clazz = NMSUtils.getNMSClassSilent("NBTCompressedStreamTools"); + try (FileInputStream fileInputStream = new FileInputStream(datFile)) { + Method a = clazz.getMethod("a", InputStream.class); + Object nbtTagCompound = a.invoke(null, fileInputStream); + Method getCompound = nbtTagCompound.getClass().getMethod("getCompound", String.class); + Object bukkit = getCompound.invoke(nbtTagCompound, "bukkit"); + Method getString = bukkit.getClass().getMethod("getString", String.class); + return String.valueOf(getString.invoke(bukkit, "lastKnownName")); + } catch (Exception ignored) { + } + return "null"; + } + + private static String translateInternal(Connection connection, String input, String output, String command) { + PreparedStatement preparedStatement = null; + ResultSet resultSet = null; + try { + preparedStatement = connection.prepareStatement(Strings.replaceWithOrder(command, sqlTable.getTableName())); + preparedStatement.setString(1, input); + resultSet = preparedStatement.executeQuery(); + while (resultSet.next()) { + return resultSet.getString(output); + } + } catch (SQLException e) { + TLogger.getGlobalLogger().error("Database error: " + e.toString()); + } finally { + SQLExecutor.freeStatement(preparedStatement, resultSet); + } + return null; + } + + // ********************************* + // + // Getter and Setter + // + // ********************************* + + public static boolean isEnabled() { + return enabled; + } +} diff --git a/src/main/java/me/skymc/taboolib/translateuuid/TranslateUUIDCommand.java b/src/main/java/me/skymc/taboolib/translateuuid/TranslateUUIDCommand.java new file mode 100644 index 0000000..0817bdd --- /dev/null +++ b/src/main/java/me/skymc/taboolib/translateuuid/TranslateUUIDCommand.java @@ -0,0 +1,75 @@ +package me.skymc.taboolib.translateuuid; + +import com.ilummc.tlib.resources.TLocale; +import me.skymc.taboolib.commands.internal.BaseMainCommand; +import me.skymc.taboolib.commands.internal.BaseSubCommand; +import me.skymc.taboolib.commands.internal.type.CommandArgument; +import me.skymc.taboolib.commands.internal.type.CommandRegister; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; + +/** + * @Author sky + * @Since 2018-06-22 17:09 + */ +public class TranslateUUIDCommand extends BaseMainCommand { + + @Override + public String getCommandTitle() { + return TLocale.asString("COMMANDS.TRANSLATE-UUID.COMMAND-TITLE"); + } + + @CommandRegister + BaseSubCommand importLocal = new BaseSubCommand() { + @Override + public String getLabel() { + return "importLocal"; + } + + @Override + public String getDescription() { + return TLocale.asString("COMMANDS.TRANSLATE-UUID.IMPORTLOCAL.DESCRIPTION"); + } + + @Override + public CommandArgument[] getArguments() { + return new CommandArgument[0]; + } + + @Override + public void onCommand(CommandSender sender, Command command, String label, String[] args) { + if (!TranslateUUID.isEnabled()) { + TLocale.sendTo(sender, "COMMANDS.TRANSLATE-UUID.IMPORTLOCAL.DISABLED"); + return; + } + + TLocale.sendTo(sender, "COMMANDS.TRANSLATE-UUID.IMPORTLOCAL.SUCCESS"); + TranslateUUID.importLocal(); + } + }; + + @CommandRegister + BaseSubCommand reload = new BaseSubCommand() { + @Override + public String getLabel() { + return "reload"; + } + + @Override + public String getDescription() { + return TLocale.asString("COMMANDS.TRANSLATE-UUID.RELOAD.DESCRIPTION"); + } + + @Override + public CommandArgument[] getArguments() { + return new CommandArgument[0]; + } + + @Override + public void onCommand(CommandSender sender, Command command, String label, String[] args) { + TLocale.sendTo(sender, "COMMANDS.TRANSLATE-UUID.RELOAD.SUCCESS"); + TranslateUUID.cancel(); + TranslateUUID.init(); + } + }; +} diff --git a/src/main/java/me/skymc/taboolib/update/UpdateTask.java b/src/main/java/me/skymc/taboolib/update/UpdateTask.java index 6d469ca..790e709 100644 --- a/src/main/java/me/skymc/taboolib/update/UpdateTask.java +++ b/src/main/java/me/skymc/taboolib/update/UpdateTask.java @@ -6,6 +6,7 @@ import com.google.gson.JsonParser; import com.ilummc.tlib.resources.TLocale; import me.skymc.taboolib.Main; import me.skymc.taboolib.TabooLib; +import me.skymc.taboolib.commands.plugin.TabooLibPluginMainCommand; import me.skymc.taboolib.fileutils.FileUtils; import org.bukkit.Bukkit; import org.bukkit.scheduler.BukkitRunnable; @@ -63,6 +64,6 @@ public class UpdateTask { } } } - }.runTaskLaterAsynchronously(Main.getInst(), 100); + }.runTaskTimerAsynchronously(Main.getInst(), 100, 20 * 60 * 60 * 6); } } diff --git a/src/main/java/org/javalite/activejdbc/MetaModel.java b/src/main/java/org/javalite/activejdbc/MetaModel.java index 55657bf..3613a89 100644 --- a/src/main/java/org/javalite/activejdbc/MetaModel.java +++ b/src/main/java/org/javalite/activejdbc/MetaModel.java @@ -163,7 +163,7 @@ public class MetaModel implements Serializable { } /** - * @return name of the column for optimistic locking record version + * @return name of the addColumn for optimistic locking record version */ public String getVersionColumn() { return versionColumn; @@ -401,11 +401,11 @@ public class MetaModel implements Serializable { } /** - * FK name is a foreign key name used in relationships as a foreign key column in a child table (table represented by this + * FK name is a foreign key name used in relationships as a foreign key addColumn in a child table (table represented by this * instance is a parent table). * The FK name is derived using {@link org.javalite.common.Inflector}: It is a singular version of this table name plus "_id". * - * @return foreign key name used in relationships as a foreign key column in a child table. + * @return foreign key name used in relationships as a foreign key addColumn in a child table. */ public String getFKName() { return singularize(getTableName()).toLowerCase() + "_id"; @@ -469,10 +469,10 @@ public class MetaModel implements Serializable { } /** - * Provides column metadata map, keyed by attribute names. + * Provides addColumn metadata map, keyed by attribute names. * Table columns correspond to ActiveJDBC model attributes. * - * @return Provides column metadata map, keyed by attribute names. + * @return Provides addColumn metadata map, keyed by attribute names. */ public Map getColumnMetadata() { if (columnMetadata == null || columnMetadata.isEmpty()) { diff --git a/src/main/resources/lang/zh_CN.yml b/src/main/resources/lang/zh_CN.yml index d1ab8ac..2a90db7 100644 --- a/src/main/resources/lang/zh_CN.yml +++ b/src/main/resources/lang/zh_CN.yml @@ -520,6 +520,15 @@ COMMANDS: INVALID-PLUGIN: '&8[&3&lTabooLib&8] &4插件 &c{0} &4不存在' INVALID-PLUGIN-IGNORED: '&8[&3&lTabooLib&8] &4插件 &c{0} &4无法操作' TRY-RELOAD: '&8[&3&lTabooLib&8] &7尝试重载插件...' + TRANSLATE-UUID: + COMMAND-TITLE: '&e&l----- &6&lTranslateUUID Commands &e&l-----' + IMPORTLOCAL: + DESCRIPTION: '导入本地数据到数据库' + DISABLED: '&8[&3&lTabooLib&8] &4该功能尚未启用' + SUCCESS: '&8[&3&lTabooLib&8] &7请求已发送, 详细信息请查看控制台' + RELOAD: + DESCRIPTION: '重载配置及数据库' + SUCCESS: '&8[&3&lTabooLib&8] &7请求已发送, 详细信息请查看控制台' DATABASE: CONNECTION-ESTABLISHED: '成功连接到 {0} 数据库,连接池大小 {1}' diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index e683e5f..ccf4e28 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -23,6 +23,9 @@ commands: permission: taboolib.admin taboolibrarymodule: aliases: [tlm] + translateuuid: + aliases: 'tuuid' + permission: taboolib.admin depend: [Vault] softdepend: [PlaceholderAPI, Skript, MassiveLag] \ No newline at end of file diff --git a/src/main/resources/translateuuid.yml b/src/main/resources/translateuuid.yml new file mode 100644 index 0000000..3e15dbb --- /dev/null +++ b/src/main/resources/translateuuid.yml @@ -0,0 +1,11 @@ +# 是否启用 +Enable: false + +# 数据库地址 +Database: + host: 'localhost' + port: '3306' + user: 'root' + password: '' + database: 'test' + table: 'taboolib_translate_uuid_database' \ No newline at end of file