From 5ef817a9b7ac59fff6173639b52f74f7e5de4c42 Mon Sep 17 00:00:00 2001 From: mlus-Asuka <1319237806@qq.com> Date: Thu, 3 Aug 2023 22:05:43 +0800 Subject: [PATCH] Use HikariPool instead of original driver.Merge Fork from KK1ve. --- README.md | 2 +- build.gradle | 49 ++--- .../vip/fubuki/playersync/PlayerSync.java | 33 ++- .../fubuki/playersync/config/JdbcConfig.java | 7 +- .../vip/fubuki/playersync/sync/ChatSync.java | 9 +- .../fubuki/playersync/sync/VanillaSync.java | 206 ++++++++++++------ .../vip/fubuki/playersync/util/JDBCsetUp.java | 52 +++-- .../playersync/util/PSThreadPoolFactory.java | 27 +++ src/main/resources/META-INF/mods.toml | 2 +- 9 files changed, 253 insertions(+), 134 deletions(-) create mode 100644 src/main/java/vip/fubuki/playersync/util/PSThreadPoolFactory.java diff --git a/README.md b/README.md index f3f9829..b21c659 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,6 @@ Such as equipment,inventory,effects,experience,food level.Any other mods support Support version now: 1.19-1.19.3 1.18.2 -1.16.5 +1.16.5 Current support Mod: curios diff --git a/build.gradle b/build.gradle index 9678c82..ec8a33b 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ plugins { id 'net.minecraftforge.gradle' version '5.1.+' } -version = '1.1.2' +version = '1.2.0' group = 'vip.fubuki.playersync' // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = 'playersync' @@ -12,25 +12,11 @@ java.toolchain.languageVersion = JavaLanguageVersion.of(17) println "Java: ${System.getProperty 'java.version'}, JVM: ${System.getProperty 'java.vm.version'} (${System.getProperty 'java.vendor'}), Arch: ${System.getProperty 'os.arch'}" minecraft { - // The mappings can be changed at any time and must be in the following format. - // Channel: Version: - // official MCVersion Official field/method names from Mojang mapping files - // parchment YYYY.MM.DD-MCVersion Open community-sourced parameter names and javadocs layered on top of official - // - // You must be aware of the Mojang license when using the 'official' or 'parchment' mappings. - // See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md - // - // Parchment is an unofficial project maintained by ParchmentMC, separate from MinecraftForge - // Additional setup is needed to use their mappings: https://github.com/ParchmentMC/Parchment/wiki/Getting-Started - // - // Use non-default mappings at your own risk. They may not always work. - // Simply re-run your setup task after changing the mappings to update your workspace. + mappings channel: 'official', version: '1.19.2' //accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') // Currently, this location cannot be changed from the default. - // Default run configurations. - // These can be tweaked, removed, or duplicated as needed. runs { client { workingDirectory project.file('run') @@ -114,33 +100,36 @@ minecraft { } } -// Include resources generated by data generators. sourceSets.main.resources { srcDir 'src/generated/resources' } repositories { maven { url = "https://maven.theillusivec4.top/" } - // Put repositories for dependencies here - // ForgeGradle automatically adds the Forge maven and Maven Central for you - // If you have mod jar dependencies in ./libs, you can declare them as a repository like so: - // flatDir { - // dir 'libs' - // } + maven { + url "https://cursemaven.com" + content { + includeGroup "curse.maven" + } + } } dependencies { minecraft 'net.minecraftforge:forge:1.19.2-43.1.1' + + jarJar("curse.maven:MySQL-561280:3685108") { + jarJar.ranged(it, '[1.0,)') + } + + jarJar("com.zaxxer:HikariCP:3.4.5") { + jarJar.ranged(it, '[3.4.5,)') + } + runtimeOnly fg.deobf("top.theillusivec4.curios:curios-forge:1.19.2-5.1.1.0") compileOnly fg.deobf("top.theillusivec4.curios:curios-forge:1.19.2-5.1.1.0:api") - // compileOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}:api") // Adds JEI API as a compile dependency - // runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}") // Adds the full JEI mod as a runtime dependency - // implementation fg.deobf("com.tterrag.registrate:Registrate:MC${mc_version}-${registrate_version}") // Adds registrate as a dependency - - // Examples using mod jars from ./libs - implementation fileTree(dir:'/libs',include:['*.jar']) - + implementation fg.deobf("curse.maven:MySQL-561280:3685108") + implementation group: 'com.zaxxer', name: 'HikariCP', version: '3.4.5' } // Example for how to get properties into the manifest for reading at runtime. diff --git a/src/main/java/vip/fubuki/playersync/PlayerSync.java b/src/main/java/vip/fubuki/playersync/PlayerSync.java index 577b6de..c753695 100644 --- a/src/main/java/vip/fubuki/playersync/PlayerSync.java +++ b/src/main/java/vip/fubuki/playersync/PlayerSync.java @@ -2,6 +2,7 @@ package vip.fubuki.playersync; import com.mojang.logging.LogUtils; import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.server.ServerStartingEvent; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.ModList; @@ -9,7 +10,6 @@ import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.config.ModConfig; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; -import net.minecraftforge.event.server.ServerStartingEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import org.slf4j.Logger; import vip.fubuki.playersync.config.JdbcConfig; @@ -30,19 +30,36 @@ public class PlayerSync ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, JdbcConfig.COMMON_CONFIG); modEventBus.addListener(this::commonSetup); MinecraftForge.EVENT_BUS.register(this); - MinecraftForge.EVENT_BUS.register(new VanillaSync()); + } + + private void commonSetup(final FMLCommonSetupEvent event) { + VanillaSync.register(); if(JdbcConfig.SYNC_CHAT.get()){ - MinecraftForge.EVENT_BUS.register(new ChatSync()); + ChatSync.register(); } } - private void commonSetup(final FMLCommonSetupEvent event) {} - @SubscribeEvent - public void onServerStarting(ServerStartingEvent event) throws SQLException, ClassNotFoundException, InstantiationException, IllegalAccessException { + public void onServerStarting(ServerStartingEvent event) throws SQLException { JDBCsetUp.executeUpdate("CREATE DATABASE IF NOT EXISTS "+JdbcConfig.DATABASE_NAME.get(),true); - JDBCsetUp.executeUpdate("CREATE TABLE IF NOT EXISTS player_data (uuid CHAR(36) NOT NULL,inventory MEDIUMBLOB,armor BLOB,advancements BLOB,enderchest MEDIUMBLOB,effects BLOB,xp int,food_level int,score int,health int,online boolean, PRIMARY KEY (uuid))"); - JDBCsetUp.executeUpdate("CREATE TABLE IF NOT EXISTS chat (player CHAR(36) NOT NULL,message TEXT,timestamp BIGINT)"); + + JDBCsetUp.executeUpdate("CREATE TABLE IF NOT EXISTS player_data (uuid CHAR(36) NOT NULL," + + "inventory MEDIUMBLOB,armor BLOB,advancements BLOB,enderchest MEDIUMBLOB,effects BLOB," + + "xp int,food_level int,score int,health int,online boolean, last_server int, PRIMARY KEY (uuid))"); + JDBCsetUp.executeUpdate("CREATE TABLE IF NOT EXISTS chat (player CHAR(36) NOT NULL,message TEXT," + + "timestamp BIGINT)"); + JDBCsetUp.executeUpdate(""" + CREATE TABLE IF NOT EXISTS server_info ( + `id` INT NOT NULL, + `enable` boolean NOT NULL, + `last_update` BIGINT NOT NULL, + PRIMARY KEY (`id`));"""); + long current = System.currentTimeMillis(); + JDBCsetUp.executeUpdate("INSERT INTO server_info(id,enable,last_update) " + + "VALUES(" + JdbcConfig.SERVER_ID.get() + ",true," + current + ") " + + "ON DUPLICATE KEY UPDATE id= " + JdbcConfig.SERVER_ID.get() +",enable = 1," + + "last_update=" + current + ";"); + if(ModList.get().isLoaded("curios")) { JDBCsetUp.executeUpdate("CREATE TABLE IF NOT EXISTS curios (uuid CHAR(36) NOT NULL,curios_item BLOB, PRIMARY KEY (uuid))"); } diff --git a/src/main/java/vip/fubuki/playersync/config/JdbcConfig.java b/src/main/java/vip/fubuki/playersync/config/JdbcConfig.java index 61800b3..5ea63df 100644 --- a/src/main/java/vip/fubuki/playersync/config/JdbcConfig.java +++ b/src/main/java/vip/fubuki/playersync/config/JdbcConfig.java @@ -4,8 +4,8 @@ package vip.fubuki.playersync.config; import net.minecraftforge.common.ForgeConfigSpec; import java.util.ArrayList; -import java.util.Collections; import java.util.List; +import java.util.Random; public class JdbcConfig { @@ -19,6 +19,8 @@ public class JdbcConfig { public static ForgeConfigSpec.BooleanValue USE_SSL; public static ForgeConfigSpec.BooleanValue SYNC_CHAT; + public static ForgeConfigSpec.ConfigValue SERVER_ID; + static { ForgeConfigSpec.Builder COMMON_BUILDER = new ForgeConfigSpec.Builder(); @@ -29,7 +31,8 @@ public class JdbcConfig { USE_SSL = COMMON_BUILDER.comment("whether use SSL").define("use_ssl", false); USERNAME = COMMON_BUILDER.comment("username").define("user_name", "root"); PASSWORD = COMMON_BUILDER.comment("password").define("password", "password"); - SYNC_WORLD = COMMON_BUILDER.comment("The worlds that will be synchronized.If running in server it is supposed to have only one").define("sync_world", new ArrayList()); + SERVER_ID = COMMON_BUILDER.comment("the server id should be unique").define("Server_id", new Random().nextInt(1,Integer.MAX_VALUE-1)); + SYNC_WORLD = COMMON_BUILDER.comment("The worlds that will be synchronized.If running in server it is supposed to have only one").define("sync_world", new ArrayList<>()); SYNC_CHAT= COMMON_BUILDER.comment("Whether synchronize chat").define("sync_chat", true); COMMON_BUILDER.pop(); COMMON_CONFIG = COMMON_BUILDER.build(); diff --git a/src/main/java/vip/fubuki/playersync/sync/ChatSync.java b/src/main/java/vip/fubuki/playersync/sync/ChatSync.java index f97e84d..6b150e9 100644 --- a/src/main/java/vip/fubuki/playersync/sync/ChatSync.java +++ b/src/main/java/vip/fubuki/playersync/sync/ChatSync.java @@ -13,20 +13,23 @@ import java.sql.SQLException; public class ChatSync { static int tick = 0; static long current = System.currentTimeMillis(); + + public static void register(){} + @SubscribeEvent - public static void onPlayerChat(net.minecraftforge.event.ServerChatEvent event) throws SQLException, ClassNotFoundException, InstantiationException, IllegalAccessException { + public static void onPlayerChat(net.minecraftforge.event.ServerChatEvent event) throws SQLException { JDBCsetUp.executeUpdate("INSERT INTO chat (player, message, timestamp) VALUES ('" + event.getUsername() + "', '" + event.getRawText() + "', '" + current + "')"); } @SubscribeEvent - public static void Tick(net.minecraftforge.event.TickEvent.ServerTickEvent event) throws SQLException, ClassNotFoundException, InstantiationException, IllegalAccessException { + public static void Tick(net.minecraftforge.event.TickEvent.ServerTickEvent event) throws SQLException { tick++; if(tick == 20) { ReadMessage(event.getServer().getPlayerList()); } } - public static void ReadMessage(PlayerList playerList) throws SQLException, ClassNotFoundException, InstantiationException, IllegalAccessException { + public static void ReadMessage(PlayerList playerList) throws SQLException { ResultSet resultSet= JDBCsetUp.executeQuery("SELECT * FROM chat WHERE timestamp > " + current); current = System.currentTimeMillis(); tick = 0; diff --git a/src/main/java/vip/fubuki/playersync/sync/VanillaSync.java b/src/main/java/vip/fubuki/playersync/sync/VanillaSync.java index 78e1940..2d67984 100644 --- a/src/main/java/vip/fubuki/playersync/sync/VanillaSync.java +++ b/src/main/java/vip/fubuki/playersync/sync/VanillaSync.java @@ -12,11 +12,13 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.event.entity.player.PlayerEvent; +import net.minecraftforge.event.server.ServerStoppedEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; import vip.fubuki.playersync.config.JdbcConfig; import vip.fubuki.playersync.util.JDBCsetUp; import vip.fubuki.playersync.util.LocalJsonUtil; +import vip.fubuki.playersync.util.PSThreadPoolFactory; import java.io.File; import java.io.IOException; @@ -27,96 +29,158 @@ import java.sql.SQLException; import java.util.HashMap; import java.util.Map; import java.util.Objects; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; @Mod.EventBusSubscriber public class VanillaSync { - @SubscribeEvent - public static void OnPlayerJoin(PlayerEvent.PlayerLoggedInEvent event) throws SQLException, ClassNotFoundException, InstantiationException, IllegalAccessException, IOException, CommandSyntaxException { + public static void register(){} + + static ExecutorService executorService = Executors.newCachedThreadPool(new PSThreadPoolFactory("PlayerSync")); + + public static void doPlayerJoin(PlayerEvent.PlayerLoggedInEvent event) throws SQLException, ClassNotFoundException, InstantiationException, IllegalAccessException, CommandSyntaxException, IOException { String player_uuid = event.getEntity().getUUID().toString(); - ResultSet resultSet=JDBCsetUp.executeQuery("SELECT online FROM player_data WHERE uuid='"+player_uuid+"'"); + ResultSet resultSet=JDBCsetUp.executeQuery("SELECT online, last_server FROM player_data WHERE uuid='"+player_uuid+"'"); ServerPlayer serverPlayer = (ServerPlayer) event.getEntity(); if(!resultSet.next()){ Store(event.getEntity(),true,Dist.CLIENT.isDedicatedServer()); return; } boolean online = resultSet.getBoolean("online"); + int lastServer = resultSet.getInt("last_server"); resultSet=JDBCsetUp.executeQuery("SELECT * FROM player_data WHERE uuid='"+player_uuid+"'"); if(online) { - serverPlayer.connection.disconnect(Component.translatable("playersync.already_online")); - }else { - JDBCsetUp.executeUpdate("UPDATE player_data SET online=true WHERE uuid='"+player_uuid+"'"); - if(resultSet.next()) { - //Easy Part - serverPlayer.setHealth(resultSet.getInt("health")); - serverPlayer.getFoodData().setFoodLevel(resultSet.getInt("food_level")); - serverPlayer.totalExperience=0; - serverPlayer.experienceLevel=0; - serverPlayer.experienceProgress=0; - serverPlayer.giveExperiencePoints(resultSet.getInt("xp")); - serverPlayer.setScore(resultSet.getInt("score")); - //Equipment - String armor_data=resultSet.getString("armor"); - if(armor_data.length()>2) { - Map equipment = LocalJsonUtil.StringToEntryMap(armor_data); - for (Map.Entry entry : equipment.entrySet()) { - serverPlayer.getInventory().armor.set(entry.getKey(), Deserialize(entry)); - } + + ResultSet getServerInfo = JDBCsetUp.executeQuery("SELECT last_update,enable FROM server_info WHERE id='"+lastServer+"'"); + if(getServerInfo.next()){ + long last_update = getServerInfo.getLong("last_update"); + boolean enable = getServerInfo.getBoolean("enable"); + if(enable && System.currentTimeMillis() < last_update + 300000.0){ + event.getEntity().removeTag("player_synced"); + serverPlayer.connection.disconnect(Component.translatable("playersync.already_online")); + return; } - //Inventory - Map inventory = LocalJsonUtil.StringToEntryMap(resultSet.getString("inventory")); - for (Map.Entry entry : inventory.entrySet()) { - serverPlayer.getInventory().setItem(entry.getKey(),Deserialize(entry)); - } - //Ender chest - Map ender_chest = LocalJsonUtil.StringToEntryMap(resultSet.getString("enderchest")); - for (Map.Entry entry : ender_chest.entrySet()) { - serverPlayer.getEnderChestInventory().setItem(entry.getKey(),Deserialize(entry)); - } - //Effects - String effectData=resultSet.getString("effects"); - if(effectData.length()>2) { - serverPlayer.removeAllEffects(); - Map effects = LocalJsonUtil.StringToEntryMap(effectData); - for (Map.Entry entry : effects.entrySet()) { - CompoundTag effectTag = NbtUtils.snbtToStructure(entry.getValue().replace("|", ",")); - MobEffectInstance mobEffectInstance = MobEffectInstance.load(effectTag); - assert mobEffectInstance != null; - serverPlayer.addEffect(mobEffectInstance); - } - } - //Advancements - File gameDir = serverPlayer.getServer().getServerDirectory(); - if(Dist.CLIENT.isDedicatedServer()){ - File advancements = new File(gameDir, JdbcConfig.SYNC_WORLD.get().get(0)+"/advancements"+"/"+player_uuid+".json"); - if (!advancements.exists()) { - advancements.createNewFile(); - } - byte [] bytes=resultSet.getString("advancements").getBytes(); - Files.write(advancements.toPath(),bytes); - }else{ - File[] files= ScanAdvancementsFile(player_uuid, gameDir); - for (File file : files) { - if(file==null) continue; - byte [] bytes=resultSet.getString("advancements").getBytes(); - Files.write(file.toPath(),bytes); - } + JDBCsetUp.executeUpdate("UPDATE server_info SET enable=false WHERE id=" + lastServer); + } + + getServerInfo.close(); + + + + } + JDBCsetUp.executeUpdate("UPDATE server_info SET last_update=" + System.currentTimeMillis() + " WHERE id=" + JdbcConfig.SERVER_ID.get()); + JDBCsetUp.executeUpdate("UPDATE player_data SET online=true,last_server=" + JdbcConfig.SERVER_ID.get() + " WHERE uuid='"+player_uuid+"'"); + if(resultSet.next()) { + //Easy Part + serverPlayer.setHealth(resultSet.getInt("health")); + serverPlayer.getFoodData().setFoodLevel(resultSet.getInt("food_level")); + serverPlayer.totalExperience=0; + serverPlayer.experienceLevel=0; + serverPlayer.experienceProgress=0; + serverPlayer.giveExperiencePoints(resultSet.getInt("xp")); + serverPlayer.setScore(resultSet.getInt("score")); + //Equipment + String armor_data=resultSet.getString("armor"); + if(armor_data.length()>2) { + Map equipment = LocalJsonUtil.StringToEntryMap(armor_data); + for (Map.Entry entry : equipment.entrySet()) { + serverPlayer.getInventory().armor.set(entry.getKey(), Deserialize(entry)); + } + } + //Inventory + Map inventory = LocalJsonUtil.StringToEntryMap(resultSet.getString("inventory")); + for (Map.Entry entry : inventory.entrySet()) { + serverPlayer.getInventory().setItem(entry.getKey(),Deserialize(entry)); + } + //Ender chest + Map ender_chest = LocalJsonUtil.StringToEntryMap(resultSet.getString("enderchest")); + for (Map.Entry entry : ender_chest.entrySet()) { + serverPlayer.getEnderChestInventory().setItem(entry.getKey(),Deserialize(entry)); + } + //Effects + String effectData=resultSet.getString("effects"); + if(effectData.length()>2) { + serverPlayer.removeAllEffects(); + Map effects = LocalJsonUtil.StringToEntryMap(effectData); + for (Map.Entry entry : effects.entrySet()) { + CompoundTag effectTag = NbtUtils.snbtToStructure(entry.getValue().replace("|", ",")); + MobEffectInstance mobEffectInstance = MobEffectInstance.load(effectTag); + assert mobEffectInstance != null; + serverPlayer.addEffect(mobEffectInstance); + } + } + //Advancements + File gameDir = Objects.requireNonNull(serverPlayer.getServer()).getServerDirectory(); + if(Dist.CLIENT.isDedicatedServer()){ + File advancements = new File(gameDir, JdbcConfig.SYNC_WORLD.get().get(0)+"/advancements"+"/"+player_uuid+".json"); + if (!advancements.exists()) { + advancements.createNewFile(); + } + byte [] bytes=resultSet.getString("advancements").getBytes(); + Files.write(advancements.toPath(),bytes); + }else{ + File[] files= ScanAdvancementsFile(player_uuid, gameDir); + for (File file : files) { + if(file==null) continue; + byte [] bytes=resultSet.getString("advancements").getBytes(); + Files.write(file.toPath(),bytes); } } - //Mod support - ModsSupport modsSupport = new ModsSupport(); - modsSupport.onPlayerJoin(serverPlayer); } + //Mod support + ModsSupport modsSupport = new ModsSupport(); + modsSupport.onPlayerJoin(serverPlayer); + serverPlayer.addTag("player_synced"); + resultSet.close(); } + @SubscribeEvent + public static void OnPlayerJoin(PlayerEvent.PlayerLoggedInEvent event){ + executorService.submit(()->{ + try { + doPlayerJoin(event); + } catch (Exception e) { + e.printStackTrace(); + } + }); + + } + private static ItemStack Deserialize(Map.Entry entry) throws CommandSyntaxException { String nbt= entry.getValue().replace("|",",").replace("^","\"").replace("<","{").replace(">","}").replace("~", "'"); CompoundTag compoundTag = NbtUtils.snbtToStructure(nbt); return ItemStack.of(compoundTag); } + + public static void doPlayerSaveToFile(PlayerEvent.SaveToFile event) throws SQLException, IOException, ClassNotFoundException, InstantiationException, IllegalAccessException { + JDBCsetUp.executeUpdate("UPDATE server_info SET last_update=" + System.currentTimeMillis() + " WHERE id=" + JdbcConfig.SERVER_ID.get()); + if(!event.getEntity().getTags().contains("player_synced")) return; + Store(event.getEntity(),false,Dist.CLIENT.isDedicatedServer()); + //Mod support + ModsSupport modsSupport = new ModsSupport(); + modsSupport.onPlayerLeave(event.getEntity()); + } + @SubscribeEvent - public static void OnPlayerLogout(PlayerEvent.PlayerLoggedOutEvent event) throws SQLException, ClassNotFoundException, InstantiationException, IllegalAccessException, IOException { + public static void onPlayerSaveToFile(PlayerEvent.SaveToFile event) { + executorService.submit(()->{ + try { + doPlayerSaveToFile(event); + } catch (Exception e) { + e.printStackTrace(); + } + }); + } + + @SubscribeEvent + public static void onServerShutdown(ServerStoppedEvent event) throws SQLException { + JDBCsetUp.executeUpdate("UPDATE server_info SET enable=false WHERE id=" + JdbcConfig.SERVER_ID.get()); + } + + public static void doPlayerLogout(PlayerEvent.PlayerLoggedOutEvent event) throws SQLException, ClassNotFoundException, InstantiationException, IllegalAccessException, IOException { + if(!event.getEntity().getTags().contains("player_synced")) return; String player_uuid = event.getEntity().getUUID().toString(); JDBCsetUp.executeUpdate("UPDATE player_data SET online=false WHERE uuid='"+player_uuid+"'"); Store(event.getEntity(),false,Dist.CLIENT.isDedicatedServer()); @@ -126,7 +190,19 @@ public class VanillaSync { event.getEntity().removeTag("player_synced"); } - public static void Store(Player player, boolean init,boolean isServer) throws SQLException, ClassNotFoundException, InstantiationException, IllegalAccessException, IOException { + @SubscribeEvent + public static void onPlayerLogout(PlayerEvent.PlayerLoggedOutEvent event) { + executorService.submit(()->{ + try { + doPlayerLogout(event); + } catch (Exception e) { + e.printStackTrace(); + } + }); + + } + + public static void Store(Player player, boolean init,boolean isServer) throws SQLException, IOException { String player_uuid = player.getUUID().toString(); //Easy part int XP = player.totalExperience; diff --git a/src/main/java/vip/fubuki/playersync/util/JDBCsetUp.java b/src/main/java/vip/fubuki/playersync/util/JDBCsetUp.java index 7ea9b8c..7311aba 100644 --- a/src/main/java/vip/fubuki/playersync/util/JDBCsetUp.java +++ b/src/main/java/vip/fubuki/playersync/util/JDBCsetUp.java @@ -1,44 +1,48 @@ package vip.fubuki.playersync.util; +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; import vip.fubuki.playersync.config.JdbcConfig; import java.sql.*; -import java.util.Properties; - public class JDBCsetUp { + private static HikariDataSource dataSource; - @SuppressWarnings("deprecation") - public static Connection getConnection(boolean init) throws InstantiationException, IllegalAccessException, ClassNotFoundException, SQLException { - Class clazz = Class.forName("com.mysql.cj.jdbc.Driver"); - Driver driver = (Driver) clazz.newInstance(); - Properties properties = new Properties(); - properties.setProperty("user",JdbcConfig.USERNAME.get()); - properties.setProperty("password",JdbcConfig.PASSWORD.get()); - String url; - if(init) { - url="jdbc:mysql://"+JdbcConfig.HOST.get()+":"+JdbcConfig.PORT.get()+"?useUnicode=true&characterEncoding=utf-8&useSSL="+JdbcConfig.USE_SSL.get()+"&serverTimezone=UTC&allowPublicKeyRetrieval=true"; - }else{ - url="jdbc:mysql://"+JdbcConfig.HOST.get()+":"+JdbcConfig.PORT.get()+"/"+JdbcConfig.DATABASE_NAME.get()+"?useUnicode=true&characterEncoding=utf-8&useSSL="+JdbcConfig.USE_SSL.get()+"&serverTimezone=UTC&allowPublicKeyRetrieval=true"; + public static void initDataSource() { + HikariConfig config = new HikariConfig(); + config.setJdbcUrl("jdbc:mysql://"+JdbcConfig.HOST.get()+":"+JdbcConfig.PORT.get()+"?useUnicode=true&characterEncoding=utf-8&useSSL="+JdbcConfig.USE_SSL.get()+"&serverTimezone=UTC&allowPublicKeyRetrieval=true"); + config.setUsername(JdbcConfig.USERNAME.get()); + config.setPassword(JdbcConfig.PASSWORD.get()); + + dataSource = new HikariDataSource(config); + } + + public static Connection getConnection() throws SQLException { + if (dataSource == null) { + initDataSource(); } - return driver.connect(url,properties); + return dataSource.getConnection(); } - public static ResultSet executeQuery(String sql) throws SQLException, InstantiationException, IllegalAccessException, ClassNotFoundException { - Statement statement= getConnection(false).createStatement(); - return statement.executeQuery(sql); + public static ResultSet executeQuery(String sql) throws SQLException{ + try (Connection connection = getConnection(); + PreparedStatement preparedStatement = connection.prepareStatement(sql)) { + return preparedStatement.executeQuery(); + } } - public static void executeUpdate(String sql) throws SQLException, InstantiationException, IllegalAccessException, ClassNotFoundException { + public static void executeUpdate(String sql) throws SQLException{ executeUpdate(sql,false); } - public static void executeUpdate(String sql,boolean init) throws SQLException, InstantiationException, IllegalAccessException, ClassNotFoundException { - Statement statement= getConnection(init).createStatement(); - if(!init) statement.executeUpdate("USE "+JdbcConfig.DATABASE_NAME.get()); - statement.executeUpdate(sql); - statement.close(); + public static void executeUpdate(String sql,boolean init) throws SQLException{ + try (Connection connection = getConnection(); + PreparedStatement preparedStatement = connection.prepareStatement(sql)) { + if(!init) preparedStatement.executeUpdate("USE "+JdbcConfig.DATABASE_NAME.get()); + preparedStatement.executeUpdate(); + } } } diff --git a/src/main/java/vip/fubuki/playersync/util/PSThreadPoolFactory.java b/src/main/java/vip/fubuki/playersync/util/PSThreadPoolFactory.java new file mode 100644 index 0000000..5d00713 --- /dev/null +++ b/src/main/java/vip/fubuki/playersync/util/PSThreadPoolFactory.java @@ -0,0 +1,27 @@ +package vip.fubuki.playersync.util; + +import org.jetbrains.annotations.NotNull; + +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicInteger; + +public class PSThreadPoolFactory implements ThreadFactory { + private final AtomicInteger threadIdx = new AtomicInteger(0); + + private final String threadNamePrefix; + + public PSThreadPoolFactory(String Prefix) { + threadNamePrefix = Prefix; + } + @Override + public Thread newThread(@NotNull Runnable runnable) { + Thread thread = new Thread(runnable); + thread.setName(threadNamePrefix + "-thread-" + threadIdx.getAndIncrement()); + return thread; + } + + + + + +} diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index 8218fe6..47935a6 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -19,7 +19,7 @@ modId="playersync" #mandatory # The version number of the mod - there's a few well known ${} variables useable here or just hardcode it # ${file.jarVersion} will substitute the value of the Implementation-Version as read from the mod's JAR file metadata # see the associated build.gradle script for how to populate this completely automatically during a build -version="1.1.3" #mandatory +version="1.2.0" #mandatory # A display name for the mod displayName="PlayerSync" #mandatory # A URL to query for updates for this mod. See the JSON update specification https://mcforge.readthedocs.io/en/latest/gettingstarted/autoupdate/