Use HikariPool instead of original driver.Merge Fork from KK1ve.
This commit is contained in:
parent
a0201cbb66
commit
5ef817a9b7
|
|
@ -4,6 +4,6 @@ Such as equipment,inventory,effects,experience,food level.Any other mods support
|
||||||
Support version now:
|
Support version now:
|
||||||
1.19-1.19.3
|
1.19-1.19.3
|
||||||
1.18.2
|
1.18.2
|
||||||
1.16.5
|
1.16.5
|
||||||
Current support Mod:
|
Current support Mod:
|
||||||
curios
|
curios
|
||||||
|
|
|
||||||
49
build.gradle
49
build.gradle
|
|
@ -4,7 +4,7 @@ plugins {
|
||||||
id 'net.minecraftforge.gradle' version '5.1.+'
|
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
|
group = 'vip.fubuki.playersync' // http://maven.apache.org/guides/mini/guide-naming-conventions.html
|
||||||
archivesBaseName = 'playersync'
|
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'}"
|
println "Java: ${System.getProperty 'java.version'}, JVM: ${System.getProperty 'java.vm.version'} (${System.getProperty 'java.vendor'}), Arch: ${System.getProperty 'os.arch'}"
|
||||||
minecraft {
|
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'
|
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.
|
//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 {
|
runs {
|
||||||
client {
|
client {
|
||||||
workingDirectory project.file('run')
|
workingDirectory project.file('run')
|
||||||
|
|
@ -114,33 +100,36 @@ minecraft {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Include resources generated by data generators.
|
|
||||||
sourceSets.main.resources { srcDir 'src/generated/resources' }
|
sourceSets.main.resources { srcDir 'src/generated/resources' }
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
maven {
|
maven {
|
||||||
url = "https://maven.theillusivec4.top/"
|
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:
|
maven {
|
||||||
// flatDir {
|
url "https://cursemaven.com"
|
||||||
// dir 'libs'
|
content {
|
||||||
// }
|
includeGroup "curse.maven"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
minecraft 'net.minecraftforge:forge:1.19.2-43.1.1'
|
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")
|
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("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
|
implementation fg.deobf("curse.maven:MySQL-561280:3685108")
|
||||||
// runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}") // Adds the full JEI mod as a runtime dependency
|
implementation group: 'com.zaxxer', name: 'HikariCP', version: '3.4.5'
|
||||||
// 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'])
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example for how to get properties into the manifest for reading at runtime.
|
// Example for how to get properties into the manifest for reading at runtime.
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package vip.fubuki.playersync;
|
||||||
|
|
||||||
import com.mojang.logging.LogUtils;
|
import com.mojang.logging.LogUtils;
|
||||||
import net.minecraftforge.common.MinecraftForge;
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
|
import net.minecraftforge.event.server.ServerStartingEvent;
|
||||||
import net.minecraftforge.eventbus.api.IEventBus;
|
import net.minecraftforge.eventbus.api.IEventBus;
|
||||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
import net.minecraftforge.fml.ModList;
|
import net.minecraftforge.fml.ModList;
|
||||||
|
|
@ -9,7 +10,6 @@ import net.minecraftforge.fml.ModLoadingContext;
|
||||||
import net.minecraftforge.fml.common.Mod;
|
import net.minecraftforge.fml.common.Mod;
|
||||||
import net.minecraftforge.fml.config.ModConfig;
|
import net.minecraftforge.fml.config.ModConfig;
|
||||||
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||||
import net.minecraftforge.event.server.ServerStartingEvent;
|
|
||||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import vip.fubuki.playersync.config.JdbcConfig;
|
import vip.fubuki.playersync.config.JdbcConfig;
|
||||||
|
|
@ -30,19 +30,36 @@ public class PlayerSync
|
||||||
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, JdbcConfig.COMMON_CONFIG);
|
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, JdbcConfig.COMMON_CONFIG);
|
||||||
modEventBus.addListener(this::commonSetup);
|
modEventBus.addListener(this::commonSetup);
|
||||||
MinecraftForge.EVENT_BUS.register(this);
|
MinecraftForge.EVENT_BUS.register(this);
|
||||||
MinecraftForge.EVENT_BUS.register(new VanillaSync());
|
}
|
||||||
|
|
||||||
|
private void commonSetup(final FMLCommonSetupEvent event) {
|
||||||
|
VanillaSync.register();
|
||||||
if(JdbcConfig.SYNC_CHAT.get()){
|
if(JdbcConfig.SYNC_CHAT.get()){
|
||||||
MinecraftForge.EVENT_BUS.register(new ChatSync());
|
ChatSync.register();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void commonSetup(final FMLCommonSetupEvent event) {}
|
|
||||||
|
|
||||||
@SubscribeEvent
|
@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 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")) {
|
if(ModList.get().isLoaded("curios")) {
|
||||||
JDBCsetUp.executeUpdate("CREATE TABLE IF NOT EXISTS curios (uuid CHAR(36) NOT NULL,curios_item BLOB, PRIMARY KEY (uuid))");
|
JDBCsetUp.executeUpdate("CREATE TABLE IF NOT EXISTS curios (uuid CHAR(36) NOT NULL,curios_item BLOB, PRIMARY KEY (uuid))");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ package vip.fubuki.playersync.config;
|
||||||
import net.minecraftforge.common.ForgeConfigSpec;
|
import net.minecraftforge.common.ForgeConfigSpec;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
|
||||||
public class JdbcConfig {
|
public class JdbcConfig {
|
||||||
|
|
@ -19,6 +19,8 @@ public class JdbcConfig {
|
||||||
public static ForgeConfigSpec.BooleanValue USE_SSL;
|
public static ForgeConfigSpec.BooleanValue USE_SSL;
|
||||||
public static ForgeConfigSpec.BooleanValue SYNC_CHAT;
|
public static ForgeConfigSpec.BooleanValue SYNC_CHAT;
|
||||||
|
|
||||||
|
public static ForgeConfigSpec.ConfigValue<Integer> SERVER_ID;
|
||||||
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ForgeConfigSpec.Builder COMMON_BUILDER = new ForgeConfigSpec.Builder();
|
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);
|
USE_SSL = COMMON_BUILDER.comment("whether use SSL").define("use_ssl", false);
|
||||||
USERNAME = COMMON_BUILDER.comment("username").define("user_name", "root");
|
USERNAME = COMMON_BUILDER.comment("username").define("user_name", "root");
|
||||||
PASSWORD = COMMON_BUILDER.comment("password").define("password", "password");
|
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<String>());
|
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);
|
SYNC_CHAT= COMMON_BUILDER.comment("Whether synchronize chat").define("sync_chat", true);
|
||||||
COMMON_BUILDER.pop();
|
COMMON_BUILDER.pop();
|
||||||
COMMON_CONFIG = COMMON_BUILDER.build();
|
COMMON_CONFIG = COMMON_BUILDER.build();
|
||||||
|
|
|
||||||
|
|
@ -13,20 +13,23 @@ import java.sql.SQLException;
|
||||||
public class ChatSync {
|
public class ChatSync {
|
||||||
static int tick = 0;
|
static int tick = 0;
|
||||||
static long current = System.currentTimeMillis();
|
static long current = System.currentTimeMillis();
|
||||||
|
|
||||||
|
public static void register(){}
|
||||||
|
|
||||||
@SubscribeEvent
|
@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 + "')");
|
JDBCsetUp.executeUpdate("INSERT INTO chat (player, message, timestamp) VALUES ('" + event.getUsername() + "', '" + event.getRawText() + "', '" + current + "')");
|
||||||
}
|
}
|
||||||
|
|
||||||
@SubscribeEvent
|
@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++;
|
tick++;
|
||||||
if(tick == 20) {
|
if(tick == 20) {
|
||||||
ReadMessage(event.getServer().getPlayerList());
|
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);
|
ResultSet resultSet= JDBCsetUp.executeQuery("SELECT * FROM chat WHERE timestamp > " + current);
|
||||||
current = System.currentTimeMillis();
|
current = System.currentTimeMillis();
|
||||||
tick = 0;
|
tick = 0;
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,13 @@ import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.event.entity.player.PlayerEvent;
|
import net.minecraftforge.event.entity.player.PlayerEvent;
|
||||||
|
import net.minecraftforge.event.server.ServerStoppedEvent;
|
||||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
import net.minecraftforge.fml.common.Mod;
|
import net.minecraftforge.fml.common.Mod;
|
||||||
import vip.fubuki.playersync.config.JdbcConfig;
|
import vip.fubuki.playersync.config.JdbcConfig;
|
||||||
import vip.fubuki.playersync.util.JDBCsetUp;
|
import vip.fubuki.playersync.util.JDBCsetUp;
|
||||||
import vip.fubuki.playersync.util.LocalJsonUtil;
|
import vip.fubuki.playersync.util.LocalJsonUtil;
|
||||||
|
import vip.fubuki.playersync.util.PSThreadPoolFactory;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
@ -27,96 +29,158 @@ import java.sql.SQLException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
@Mod.EventBusSubscriber
|
@Mod.EventBusSubscriber
|
||||||
public class VanillaSync {
|
public class VanillaSync {
|
||||||
|
|
||||||
@SubscribeEvent
|
public static void register(){}
|
||||||
public static void OnPlayerJoin(PlayerEvent.PlayerLoggedInEvent event) throws SQLException, ClassNotFoundException, InstantiationException, IllegalAccessException, IOException, CommandSyntaxException {
|
|
||||||
|
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();
|
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();
|
ServerPlayer serverPlayer = (ServerPlayer) event.getEntity();
|
||||||
if(!resultSet.next()){
|
if(!resultSet.next()){
|
||||||
Store(event.getEntity(),true,Dist.CLIENT.isDedicatedServer());
|
Store(event.getEntity(),true,Dist.CLIENT.isDedicatedServer());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
boolean online = resultSet.getBoolean("online");
|
boolean online = resultSet.getBoolean("online");
|
||||||
|
int lastServer = resultSet.getInt("last_server");
|
||||||
resultSet=JDBCsetUp.executeQuery("SELECT * FROM player_data WHERE uuid='"+player_uuid+"'");
|
resultSet=JDBCsetUp.executeQuery("SELECT * FROM player_data WHERE uuid='"+player_uuid+"'");
|
||||||
if(online) {
|
if(online) {
|
||||||
serverPlayer.connection.disconnect(Component.translatable("playersync.already_online"));
|
|
||||||
}else {
|
ResultSet getServerInfo = JDBCsetUp.executeQuery("SELECT last_update,enable FROM server_info WHERE id='"+lastServer+"'");
|
||||||
JDBCsetUp.executeUpdate("UPDATE player_data SET online=true WHERE uuid='"+player_uuid+"'");
|
if(getServerInfo.next()){
|
||||||
if(resultSet.next()) {
|
long last_update = getServerInfo.getLong("last_update");
|
||||||
//Easy Part
|
boolean enable = getServerInfo.getBoolean("enable");
|
||||||
serverPlayer.setHealth(resultSet.getInt("health"));
|
if(enable && System.currentTimeMillis() < last_update + 300000.0){
|
||||||
serverPlayer.getFoodData().setFoodLevel(resultSet.getInt("food_level"));
|
event.getEntity().removeTag("player_synced");
|
||||||
serverPlayer.totalExperience=0;
|
serverPlayer.connection.disconnect(Component.translatable("playersync.already_online"));
|
||||||
serverPlayer.experienceLevel=0;
|
return;
|
||||||
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<Integer, String> equipment = LocalJsonUtil.StringToEntryMap(armor_data);
|
|
||||||
for (Map.Entry<Integer, String> entry : equipment.entrySet()) {
|
|
||||||
serverPlayer.getInventory().armor.set(entry.getKey(), Deserialize(entry));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
//Inventory
|
JDBCsetUp.executeUpdate("UPDATE server_info SET enable=false WHERE id=" + lastServer);
|
||||||
Map<Integer,String> inventory = LocalJsonUtil.StringToEntryMap(resultSet.getString("inventory"));
|
}
|
||||||
for (Map.Entry<Integer, String> entry : inventory.entrySet()) {
|
|
||||||
serverPlayer.getInventory().setItem(entry.getKey(),Deserialize(entry));
|
getServerInfo.close();
|
||||||
}
|
|
||||||
//Ender chest
|
|
||||||
Map<Integer,String> ender_chest = LocalJsonUtil.StringToEntryMap(resultSet.getString("enderchest"));
|
|
||||||
for (Map.Entry<Integer, String> entry : ender_chest.entrySet()) {
|
}
|
||||||
serverPlayer.getEnderChestInventory().setItem(entry.getKey(),Deserialize(entry));
|
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+"'");
|
||||||
//Effects
|
if(resultSet.next()) {
|
||||||
String effectData=resultSet.getString("effects");
|
//Easy Part
|
||||||
if(effectData.length()>2) {
|
serverPlayer.setHealth(resultSet.getInt("health"));
|
||||||
serverPlayer.removeAllEffects();
|
serverPlayer.getFoodData().setFoodLevel(resultSet.getInt("food_level"));
|
||||||
Map<Integer, String> effects = LocalJsonUtil.StringToEntryMap(effectData);
|
serverPlayer.totalExperience=0;
|
||||||
for (Map.Entry<Integer, String> entry : effects.entrySet()) {
|
serverPlayer.experienceLevel=0;
|
||||||
CompoundTag effectTag = NbtUtils.snbtToStructure(entry.getValue().replace("|", ","));
|
serverPlayer.experienceProgress=0;
|
||||||
MobEffectInstance mobEffectInstance = MobEffectInstance.load(effectTag);
|
serverPlayer.giveExperiencePoints(resultSet.getInt("xp"));
|
||||||
assert mobEffectInstance != null;
|
serverPlayer.setScore(resultSet.getInt("score"));
|
||||||
serverPlayer.addEffect(mobEffectInstance);
|
//Equipment
|
||||||
}
|
String armor_data=resultSet.getString("armor");
|
||||||
}
|
if(armor_data.length()>2) {
|
||||||
//Advancements
|
Map<Integer, String> equipment = LocalJsonUtil.StringToEntryMap(armor_data);
|
||||||
File gameDir = serverPlayer.getServer().getServerDirectory();
|
for (Map.Entry<Integer, String> entry : equipment.entrySet()) {
|
||||||
if(Dist.CLIENT.isDedicatedServer()){
|
serverPlayer.getInventory().armor.set(entry.getKey(), Deserialize(entry));
|
||||||
File advancements = new File(gameDir, JdbcConfig.SYNC_WORLD.get().get(0)+"/advancements"+"/"+player_uuid+".json");
|
}
|
||||||
if (!advancements.exists()) {
|
}
|
||||||
advancements.createNewFile();
|
//Inventory
|
||||||
}
|
Map<Integer,String> inventory = LocalJsonUtil.StringToEntryMap(resultSet.getString("inventory"));
|
||||||
byte [] bytes=resultSet.getString("advancements").getBytes();
|
for (Map.Entry<Integer, String> entry : inventory.entrySet()) {
|
||||||
Files.write(advancements.toPath(),bytes);
|
serverPlayer.getInventory().setItem(entry.getKey(),Deserialize(entry));
|
||||||
}else{
|
}
|
||||||
File[] files= ScanAdvancementsFile(player_uuid, gameDir);
|
//Ender chest
|
||||||
for (File file : files) {
|
Map<Integer,String> ender_chest = LocalJsonUtil.StringToEntryMap(resultSet.getString("enderchest"));
|
||||||
if(file==null) continue;
|
for (Map.Entry<Integer, String> entry : ender_chest.entrySet()) {
|
||||||
byte [] bytes=resultSet.getString("advancements").getBytes();
|
serverPlayer.getEnderChestInventory().setItem(entry.getKey(),Deserialize(entry));
|
||||||
Files.write(file.toPath(),bytes);
|
}
|
||||||
}
|
//Effects
|
||||||
|
String effectData=resultSet.getString("effects");
|
||||||
|
if(effectData.length()>2) {
|
||||||
|
serverPlayer.removeAllEffects();
|
||||||
|
Map<Integer, String> effects = LocalJsonUtil.StringToEntryMap(effectData);
|
||||||
|
for (Map.Entry<Integer, String> 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();
|
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<Integer, String> entry) throws CommandSyntaxException {
|
private static ItemStack Deserialize(Map.Entry<Integer, String> entry) throws CommandSyntaxException {
|
||||||
String nbt= entry.getValue().replace("|",",").replace("^","\"").replace("<","{").replace(">","}").replace("~", "'");
|
String nbt= entry.getValue().replace("|",",").replace("^","\"").replace("<","{").replace(">","}").replace("~", "'");
|
||||||
CompoundTag compoundTag = NbtUtils.snbtToStructure(nbt);
|
CompoundTag compoundTag = NbtUtils.snbtToStructure(nbt);
|
||||||
return ItemStack.of(compoundTag);
|
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
|
@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();
|
String player_uuid = event.getEntity().getUUID().toString();
|
||||||
JDBCsetUp.executeUpdate("UPDATE player_data SET online=false WHERE uuid='"+player_uuid+"'");
|
JDBCsetUp.executeUpdate("UPDATE player_data SET online=false WHERE uuid='"+player_uuid+"'");
|
||||||
Store(event.getEntity(),false,Dist.CLIENT.isDedicatedServer());
|
Store(event.getEntity(),false,Dist.CLIENT.isDedicatedServer());
|
||||||
|
|
@ -126,7 +190,19 @@ public class VanillaSync {
|
||||||
event.getEntity().removeTag("player_synced");
|
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();
|
String player_uuid = player.getUUID().toString();
|
||||||
//Easy part
|
//Easy part
|
||||||
int XP = player.totalExperience;
|
int XP = player.totalExperience;
|
||||||
|
|
|
||||||
|
|
@ -1,44 +1,48 @@
|
||||||
package vip.fubuki.playersync.util;
|
package vip.fubuki.playersync.util;
|
||||||
|
|
||||||
|
import com.zaxxer.hikari.HikariConfig;
|
||||||
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
import vip.fubuki.playersync.config.JdbcConfig;
|
import vip.fubuki.playersync.config.JdbcConfig;
|
||||||
|
|
||||||
import java.sql.*;
|
import java.sql.*;
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public class JDBCsetUp {
|
public class JDBCsetUp {
|
||||||
|
|
||||||
|
private static HikariDataSource dataSource;
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
public static void initDataSource() {
|
||||||
public static Connection getConnection(boolean init) throws InstantiationException, IllegalAccessException, ClassNotFoundException, SQLException {
|
HikariConfig config = new HikariConfig();
|
||||||
Class<?> clazz = Class.forName("com.mysql.cj.jdbc.Driver");
|
config.setJdbcUrl("jdbc:mysql://"+JdbcConfig.HOST.get()+":"+JdbcConfig.PORT.get()+"?useUnicode=true&characterEncoding=utf-8&useSSL="+JdbcConfig.USE_SSL.get()+"&serverTimezone=UTC&allowPublicKeyRetrieval=true");
|
||||||
Driver driver = (Driver) clazz.newInstance();
|
config.setUsername(JdbcConfig.USERNAME.get());
|
||||||
Properties properties = new Properties();
|
config.setPassword(JdbcConfig.PASSWORD.get());
|
||||||
properties.setProperty("user",JdbcConfig.USERNAME.get());
|
|
||||||
properties.setProperty("password",JdbcConfig.PASSWORD.get());
|
dataSource = new HikariDataSource(config);
|
||||||
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";
|
public static Connection getConnection() throws SQLException {
|
||||||
}else{
|
if (dataSource == null) {
|
||||||
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";
|
initDataSource();
|
||||||
}
|
}
|
||||||
return driver.connect(url,properties);
|
return dataSource.getConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ResultSet executeQuery(String sql) throws SQLException, InstantiationException, IllegalAccessException, ClassNotFoundException {
|
public static ResultSet executeQuery(String sql) throws SQLException{
|
||||||
Statement statement= getConnection(false).createStatement();
|
try (Connection connection = getConnection();
|
||||||
return statement.executeQuery(sql);
|
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);
|
executeUpdate(sql,false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void executeUpdate(String sql,boolean init) throws SQLException, InstantiationException, IllegalAccessException, ClassNotFoundException {
|
public static void executeUpdate(String sql,boolean init) throws SQLException{
|
||||||
Statement statement= getConnection(init).createStatement();
|
try (Connection connection = getConnection();
|
||||||
if(!init) statement.executeUpdate("USE "+JdbcConfig.DATABASE_NAME.get());
|
PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
|
||||||
statement.executeUpdate(sql);
|
if(!init) preparedStatement.executeUpdate("USE "+JdbcConfig.DATABASE_NAME.get());
|
||||||
statement.close();
|
preparedStatement.executeUpdate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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
|
# 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
|
# ${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
|
# 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
|
# A display name for the mod
|
||||||
displayName="PlayerSync" #mandatory
|
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/
|
# A URL to query for updates for this mod. See the JSON update specification https://mcforge.readthedocs.io/en/latest/gettingstarted/autoupdate/
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user