not done yet

This commit is contained in:
mlus 2025-06-06 21:17:22 +08:00
parent 79e0e2cbe4
commit 3b442fbee1
7 changed files with 139 additions and 177 deletions

View File

@ -1,7 +1,7 @@
plugins { plugins {
id 'java-library' id 'java-library'
id 'maven-publish' id 'maven-publish'
id 'net.neoforged.moddev' version '2.0.86' id 'net.neoforged.gradle.userdev' version '7.0.170'
id 'idea' id 'idea'
} }
@ -46,99 +46,50 @@ base {
archivesName = mod_id archivesName = mod_id
} }
// Mojang ships Java 17 to end users from 1.18 to 1.20.4, so your mod should target Java 17. java.toolchain.languageVersion = JavaLanguageVersion.of(21)
java.toolchain.languageVersion = JavaLanguageVersion.of(17)
neoForge { //parchment {
// Specify the version of NeoForge to use. // mappingsVersion = project.parchment_mappings_version
version = project.neo_version // minecraftVersion = project.parchment_minecraft_version
//}
parchment { // accessTransformers = project.files('src/main/resources/META-INF/accesstransformer.cfg')
mappingsVersion = project.parchment_mappings_version
minecraftVersion = project.parchment_minecraft_version runs {
configureEach {
systemProperty 'forge.logging.markers', 'REGISTRIES'
systemProperty 'forge.logging.console.level', 'debug'
modSource project.sourceSets.main
} }
// This line is optional. Access Transformers are automatically detected client {
// accessTransformers = project.files('src/main/resources/META-INF/accesstransformer.cfg') client()
systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id
// Default run configurations.
// These can be tweaked, removed, or duplicated as needed.
runs {
client {
client()
// Comma-separated list of namespaces to load gametests from. Empty = all namespaces.
systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id
}
server {
server()
programArgument '--nogui'
systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id
}
// This run config launches GameTestServer and runs all registered gametests, then exits.
// By default, the server will crash when no gametests are provided.
// The gametest system is also enabled by default for other run configs under the /test command.
gameTestServer {
type = "gameTestServer"
systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id
}
data {
data()
// example of overriding the workingDirectory set in configureEach above, uncomment if you want to use it
// gameDirectory = project.file('run-data')
// Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources.
programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath()
}
// applies to all the run configs above
configureEach {
// Recommended logging data for a userdev environment
// The markers can be added/remove as needed separated by commas.
// "SCAN": For mods scan.
// "REGISTRIES": For firing of registry events.
// "REGISTRYDUMP": For getting the contents of all registries.
systemProperty 'forge.logging.markers', 'REGISTRIES'
// Recommended logging level for the console
// You can set various levels here.
// Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
logLevel = org.slf4j.event.Level.DEBUG
}
} }
mods { server {
// define mod <-> source bindings server()
// these are used to tell the game which sources are for which mod programArgument '--nogui'
// multi mod projects should define one per mod systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id
"${mod_id}" { }
sourceSet(sourceSets.main)
} gameTestServer {
systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id
}
data {
programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath()
} }
} }
// Include resources generated by data generators. // Include resources generated by data generators.
sourceSets.main.resources { srcDir 'src/generated/resources' } sourceSets.main.resources { srcDir 'src/generated/resources' }
// Sets up a dependency configuration called 'localRuntime'.
// This configuration should be used instead of 'runtimeOnly' to declare
// a dependency that will be present for runtime testing but that is
// "optional", meaning it will not be pulled by dependents of this mod.
configurations {
runtimeClasspath.extendsFrom localRuntime
}
dependencies { dependencies {
// Example optional mod dependency with JEI implementation "net.neoforged:neoforge:${neo_version}"
// The JEI API is declared for compile time use, while the full JEI artifact is used at runtime
// compileOnly "mezz.jei:jei-${mc_version}-common-api:${jei_version}"
// compileOnly "mezz.jei:jei-${mc_version}-neoforge-api:${jei_version}"
// We add the full version to localRuntime, not runtimeOnly, so that we do not publish a dependency on it
// localRuntime "mezz.jei:jei-${mc_version}-neoforge:${jei_version}"
compileOnly "maven.modrinth:curios:7.4.3+1.20.4" compileOnly "maven.modrinth:curios:7.4.3+1.20.4"
compileOnly "curse.maven:sophisticated-backpacks-422301:5297718" compileOnly "curse.maven:sophisticated-backpacks-422301:5297718"
compileOnly "curse.maven:sophisticated-core-618298:5296142" compileOnly "curse.maven:sophisticated-core-618298:5296142"
@ -157,7 +108,7 @@ dependencies {
// embedd the JDBC driver in the mod using jarJar // embedd the JDBC driver in the mod using jarJar
runtimeOnly "com.mysql:mysql-connector-j:${jdbc_version}" runtimeOnly "com.mysql:mysql-connector-j:${jdbc_version}"
jarJar "com.mysql:mysql-connector-j:${jdbc_version}" jarJar "com.mysql:mysql-connector-j:${jdbc_version}"
additionalRuntimeClasspath "com.mysql:mysql-connector-j:${jdbc_version}" // runtimeClasspath "com.mysql:mysql-connector-j:${jdbc_version}"
// For more info: // For more info:
// http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html
@ -185,11 +136,6 @@ var generateModMetadata = tasks.register("generateModMetadata", ProcessResources
from "src/main/templates" from "src/main/templates"
into "build/generated/sources/modMetadata" into "build/generated/sources/modMetadata"
} }
// Include the output of "generateModMetadata" as an input directory for the build
// this works with both building through Gradle and the IDE.
sourceSets.main.resources.srcDir generateModMetadata
// To avoid having to run "generateModMetadata" manually, make it run on every project reload
neoForge.ideSyncTask generateModMetadata
// Example configuration to allow publishing using the maven-publish plugin // Example configuration to allow publishing using the maven-publish plugin
publishing { publishing {

View File

@ -7,23 +7,19 @@ org.gradle.configuration-cache=true
#read more on this at https://github.com/neoforged/ModDevGradle?tab=readme-ov-file#better-minecraft-parameter-names--javadoc-parchment #read more on this at https://github.com/neoforged/ModDevGradle?tab=readme-ov-file#better-minecraft-parameter-names--javadoc-parchment
# you can also find the latest versions at: https://parchmentmc.org/docs/getting-started # you can also find the latest versions at: https://parchmentmc.org/docs/getting-started
parchment_minecraft_version=1.20.4 parchment_minecraft_version=1.21.1
parchment_mappings_version=2024.04.14 parchment_mappings_version=2024.11.17
# Environment Properties # Environment Properties
# You can find the latest versions here: https://projects.neoforged.net/neoforged/neoforge # You can find the latest versions here: https://projects.neoforged.net/neoforged/neoforge
# The Minecraft version must agree with the Neo version to get a valid artifact # The Minecraft version must agree with the Neo version to get a valid artifact
minecraft_version=1.20.4 minecraft_version=1.21.1
# The Minecraft version range can use any release version of Minecraft as bounds. # The Minecraft version range can use any release version of Minecraft as bounds.
# Snapshots, pre-releases, and release candidates are not guaranteed to sort properly # Snapshots, pre-releases, and release candidates are not guaranteed to sort properly
# as they do not follow standard versioning conventions. # as they do not follow standard versioning conventions.
minecraft_version_range=[1.20.4] minecraft_version_range=[1.21,1.21.3)
# The Neo version must agree with the Minecraft version to get a valid artifact neo_version=21.1.137
neo_version=20.4.248 neo_version_range=[21.1.128,)
# The Neo version range can use any version of Neo as bounds loader_version_range=[4,)
neo_version_range=[20.4.248,)
# The loader version range can only use the major version of FML as bounds
loader_version_range=[1,)
## Mod Properties ## Mod Properties
# The unique mod identifier for the mod. Must be lowercase in English locale. Must fit the regex [a-z][a-z0-9_]{1,63} # The unique mod identifier for the mod. Must be lowercase in English locale. Must fit the regex [a-z][a-z0-9_]{1,63}

View File

@ -4,11 +4,11 @@ import com.mojang.brigadier.CommandDispatcher;
import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands; import net.minecraft.commands.Commands;
import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.Mod; import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.event.RegisterCommandsEvent; import net.neoforged.neoforge.event.RegisterCommandsEvent;
import vip.fubuki.playersync.sync.chat.ChatSyncClient; import vip.fubuki.playersync.sync.chat.ChatSyncClient;
@Mod.EventBusSubscriber() @EventBusSubscriber()
public class CommandInit { public class CommandInit {
@SubscribeEvent @SubscribeEvent

View File

@ -0,0 +1,18 @@
package vip.fubuki.playersync;
import com.mojang.serialization.Codec;
import net.minecraft.core.component.DataComponentType;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.codec.ByteBufCodecs;
import net.neoforged.neoforge.registries.DeferredHolder;
import net.neoforged.neoforge.registries.DeferredRegister;
public class DataComponentTypes {
public static final DeferredRegister<DataComponentType<?>> REGISTRY = DeferredRegister.create(Registries.DATA_COMPONENT_TYPE, PlayerSync.MODID);
public static final DeferredHolder<DataComponentType<?>, DataComponentType<String>> ORIGINAL_ITEM_NBT =
REGISTRY.register("original_item_nbt", () -> DataComponentType.<String>builder().persistent(Codec.STRING).networkSynchronized(ByteBufCodecs.STRING_UTF8).build());
public static final DeferredHolder<DataComponentType<?>, DataComponentType<String>> ORIGINAL_ITEM_ID =
REGISTRY.register("original_item_id", () -> DataComponentType.<String>builder().persistent(Codec.STRING).networkSynchronized(ByteBufCodecs.STRING_UTF8).build());
public static final DeferredHolder<DataComponentType<?>, DataComponentType<String>> UNIQUE_ID =
REGISTRY.register("unique_id", () -> DataComponentType.<String>builder().persistent(Codec.STRING).networkSynchronized(ByteBufCodecs.STRING_UTF8).build());
}

View File

@ -1,6 +1,15 @@
package vip.fubuki.playersync; package vip.fubuki.playersync;
import com.mojang.logging.LogUtils; import com.mojang.logging.LogUtils;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.ModContainer;
import net.neoforged.fml.ModList;
import net.neoforged.fml.common.Mod;
import net.neoforged.fml.config.ModConfig;
import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.event.server.ServerStartingEvent;
import org.slf4j.Logger; import org.slf4j.Logger;
import vip.fubuki.playersync.config.JdbcConfig; import vip.fubuki.playersync.config.JdbcConfig;
import vip.fubuki.playersync.sync.ChatSync; import vip.fubuki.playersync.sync.ChatSync;
@ -11,27 +20,17 @@ import java.sql.Connection;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.ModList;
import net.neoforged.fml.ModLoadingContext;
import net.neoforged.fml.common.Mod;
import net.neoforged.fml.config.ModConfig;
import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;
import net.neoforged.fml.javafmlmod.FMLJavaModLoadingContext;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.event.server.ServerStartingEvent;
import net.neoforged.bus.api.IEventBus;
@Mod(PlayerSync.MODID) @Mod(PlayerSync.MODID)
public class PlayerSync { public class PlayerSync {
public static final String MODID = "playersync"; public static final String MODID = "playersync";
public static final Logger LOGGER = LogUtils.getLogger(); public static final Logger LOGGER = LogUtils.getLogger();
public PlayerSync(IEventBus modEventBus) { public PlayerSync(IEventBus modEventBus, ModContainer modContainer) {
DataComponentTypes.REGISTRY.register(modEventBus);
modEventBus.addListener(this::commonSetup); modEventBus.addListener(this::commonSetup);
NeoForge.EVENT_BUS.register(this); NeoForge.EVENT_BUS.register(this);
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, JdbcConfig.COMMON_CONFIG); modContainer.registerConfig(ModConfig.Type.COMMON, JdbcConfig.COMMON_CONFIG);
} }
private void commonSetup(final FMLCommonSetupEvent event) { private void commonSetup(final FMLCommonSetupEvent event) {

View File

@ -6,6 +6,11 @@ import net.minecraft.nbt.NbtUtils;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.neoforged.fml.ModList; import net.neoforged.fml.ModList;
import net.neoforged.neoforge.server.ServerLifecycleHooks;
import top.theillusivec4.curios.api.CuriosApi;
import top.theillusivec4.curios.api.type.capability.ICuriosItemHandler;
import top.theillusivec4.curios.api.type.inventory.ICurioStacksHandler;
import top.theillusivec4.curios.api.type.inventory.IDynamicStackHandler;
import vip.fubuki.playersync.PlayerSync; import vip.fubuki.playersync.PlayerSync;
import vip.fubuki.playersync.util.JDBCsetUp; import vip.fubuki.playersync.util.JDBCsetUp;
import vip.fubuki.playersync.util.LocalJsonUtil; import vip.fubuki.playersync.util.LocalJsonUtil;
@ -14,11 +19,6 @@ import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import top.theillusivec4.curios.api.CuriosApi;
import top.theillusivec4.curios.api.type.capability.ICuriosItemHandler;
import top.theillusivec4.curios.api.type.inventory.ICurioStacksHandler;
import top.theillusivec4.curios.api.type.inventory.IDynamicStackHandler;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
@ -75,7 +75,7 @@ public class ModsSupport {
try { try {
String nbtString = VanillaSync.deserializeString(serialized); String nbtString = VanillaSync.deserializeString(serialized);
CompoundTag tag = NbtUtils.snbtToStructure(nbtString); CompoundTag tag = NbtUtils.snbtToStructure(nbtString);
ItemStack stack = ItemStack.of(tag); ItemStack stack = ItemStack.parse(ServerLifecycleHooks.getCurrentServer().registryAccess(),tag).get();
if (handler.getCurios().containsKey(slotType)) { if (handler.getCurios().containsKey(slotType)) {
ICurioStacksHandler stacksHandler = handler.getCurios().get(slotType); ICurioStacksHandler stacksHandler = handler.getCurios().get(slotType);
IDynamicStackHandler dynStacks = stacksHandler.getStacks(); IDynamicStackHandler dynStacks = stacksHandler.getStacks();

View File

@ -2,8 +2,13 @@ package vip.fubuki.playersync.sync;
import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.nbt.*; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.Style; import net.minecraft.network.chat.Style;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
@ -17,15 +22,18 @@ import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items; import net.minecraft.world.item.Items;
import net.minecraft.world.item.component.ItemLore;
import net.minecraft.world.level.storage.WorldData; import net.minecraft.world.level.storage.WorldData;
import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.ModList; import net.neoforged.fml.ModList;
import net.neoforged.fml.common.Mod; import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.event.OnDatapackSyncEvent; import net.neoforged.neoforge.event.OnDatapackSyncEvent;
import net.neoforged.neoforge.event.TickEvent;
import net.neoforged.neoforge.event.entity.player.PlayerEvent; import net.neoforged.neoforge.event.entity.player.PlayerEvent;
import net.neoforged.neoforge.event.server.ServerStoppedEvent; import net.neoforged.neoforge.event.server.ServerStoppedEvent;
import net.neoforged.neoforge.event.tick.LevelTickEvent;
import net.neoforged.neoforge.event.tick.ServerTickEvent;
import net.neoforged.neoforge.server.ServerLifecycleHooks; import net.neoforged.neoforge.server.ServerLifecycleHooks;
import vip.fubuki.playersync.DataComponentTypes;
import vip.fubuki.playersync.PlayerSync; import vip.fubuki.playersync.PlayerSync;
import vip.fubuki.playersync.config.JdbcConfig; import vip.fubuki.playersync.config.JdbcConfig;
import vip.fubuki.playersync.util.JDBCsetUp; import vip.fubuki.playersync.util.JDBCsetUp;
@ -42,7 +50,7 @@ import java.util.*;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
@Mod.EventBusSubscriber @EventBusSubscriber
public class VanillaSync { public class VanillaSync {
public static void register() {} public static void register() {}
@ -74,7 +82,7 @@ public class VanillaSync {
} }
// Restore Advancements // Restore Advancements
File gameDir = Objects.requireNonNull(serverPlayer.getServer()).getServerDirectory(); File gameDir = Objects.requireNonNull(serverPlayer.getServer()).getServerDirectory().toFile();
final MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); final MinecraftServer server = ServerLifecycleHooks.getCurrentServer();
if (server != null && server.isDedicatedServer()) { if (server != null && server.isDedicatedServer()) {
@ -269,7 +277,7 @@ public class VanillaSync {
if (BuiltInRegistries.ITEM.containsKey(registryName)) { if (BuiltInRegistries.ITEM.containsKey(registryName)) {
// Item exists (could be vanilla or a loaded mod item), restore normally // Item exists (could be vanilla or a loaded mod item), restore normally
try { try {
ItemStack restoredItem = ItemStack.of(compoundTag); ItemStack restoredItem = ItemStack.parse(ServerLifecycleHooks.getCurrentServer().registryAccess(),compoundTag).get();
// Only return the restored item if the ItemStack.of did not unexpectedly // Only return the restored item if the ItemStack.of did not unexpectedly
// returned an empty item // returned an empty item
// Either the item is not empty, or it is empty and the original tag was also // Either the item is not empty, or it is empty and the original tag was also
@ -293,29 +301,24 @@ public class VanillaSync {
PlayerSync.LOGGER.debug("Item {} not found in registry. Creating placeholder.", registryName); PlayerSync.LOGGER.debug("Item {} not found in registry. Creating placeholder.", registryName);
ItemStack placeholder = new ItemStack(Items.PAPER); ItemStack placeholder = new ItemStack(Items.PAPER);
CompoundTag placeholderNbt = placeholder.getOrCreateTag();
// Store the original serialized NBT string, not the parsed CompoundTag string // Store the original serialized NBT string, not the parsed CompoundTag string
placeholderNbt.putString("playersync:original_item_nbt", serializedNbt); placeholder.set(DataComponentTypes.ORIGINAL_ITEM_NBT.get(), serializedNbt);
placeholderNbt.putString("playersync:original_item_id", registryName.toString()); placeholder.set(DataComponentTypes.ORIGINAL_ITEM_ID.get(), registryName.toString());
// Add a unique UUID to ensure the item is unstackable // Add a unique UUID to ensure the item is unstackable
// Stacked placerholders would be converted into a single item when restoring item // Stacked placerholders would be converted into a single item when restoring item
placeholderNbt.putUUID("playersync:unique_id", UUID.randomUUID()); placeholder.set(DataComponentTypes.UNIQUE_ID.get(), UUID.randomUUID().toString());
// Add display name and lore // Add display name and lore
CompoundTag displayTag = placeholderNbt.getCompound("display");
if (!placeholderNbt.contains("display"))
placeholderNbt.put("display", displayTag);
String placeholderItemTitleOverride = JdbcConfig.ITEM_PLACEHOLDER_TITLE_OVERRIDE.get(); String placeholderItemTitleOverride = JdbcConfig.ITEM_PLACEHOLDER_TITLE_OVERRIDE.get();
displayTag.putString("Name", Component.Serializer.toJson( placeholder.set(DataComponents.ITEM_NAME,
Component Component
.literal(placeholderItemTitleOverride != null && !placeholderItemTitleOverride.isBlank() .literal(placeholderItemTitleOverride != null && !placeholderItemTitleOverride.isBlank()
? placeholderItemTitleOverride ? placeholderItemTitleOverride
: Component.translatable("playersync.item_placeholder_title").getString()) : Component.translatable("playersync.item_placeholder_title").getString())
.setStyle(Style.EMPTY.withColor(ChatFormatting.RED).withItalic(true)))); .setStyle(Style.EMPTY.withColor(ChatFormatting.RED).withItalic(true)));
ListTag loreList = new ListTag(); List<Component> loreList = new ArrayList<>();
String placeholderItemDetails = registryName.toString(); String placeholderItemDetails = registryName.toString();
// add a stack size if it is available // add a stack size if it is available
@ -325,11 +328,11 @@ public class VanillaSync {
placeholderItemDetails = placeholderItemAmount + "x " + placeholderItemDetails; placeholderItemDetails = placeholderItemAmount + "x " + placeholderItemDetails;
} }
loreList.add(StringTag.valueOf(Component.Serializer.toJson( loreList.add(
Component.literal(placeholderItemDetails) Component.literal(placeholderItemDetails)
.setStyle(Style.EMPTY.withColor(ChatFormatting.GRAY).withItalic(false))))); .setStyle(Style.EMPTY.withColor(ChatFormatting.GRAY).withItalic(false)));
// add newline // add newline
loreList.add(StringTag.valueOf(Component.Serializer.toJson(Component.literal("")))); loreList.add(Component.literal(""));
String placeholderItemDescriptionOverride = JdbcConfig.ITEM_PLACEHOLDER_DESCRIPTION_OVERRIDE.get(); String placeholderItemDescriptionOverride = JdbcConfig.ITEM_PLACEHOLDER_DESCRIPTION_OVERRIDE.get();
String placeholderItemDescriptionLines = placeholderItemDescriptionOverride != null && ! placeholderItemDescriptionOverride.isBlank() String placeholderItemDescriptionLines = placeholderItemDescriptionOverride != null && ! placeholderItemDescriptionOverride.isBlank()
@ -337,11 +340,12 @@ public class VanillaSync {
: Component.translatable("playersync.item_placeholder_description").getString(); : Component.translatable("playersync.item_placeholder_description").getString();
for (String descriptionLine : placeholderItemDescriptionLines.split("\n")) { for (String descriptionLine : placeholderItemDescriptionLines.split("\n")) {
loreList.add(StringTag.valueOf(Component.Serializer.toJson( loreList.add(
Component.literal(descriptionLine) Component.literal(descriptionLine)
.setStyle(Style.EMPTY.withColor(ChatFormatting.DARK_GRAY))))); .setStyle(Style.EMPTY.withColor(ChatFormatting.DARK_GRAY)));
} }
displayTag.put("Lore", loreList);
placeholder.set(DataComponents.LORE,new ItemLore(loreList));
return placeholder; return placeholder;
} }
@ -437,9 +441,9 @@ public class VanillaSync {
// Helper function to get the NBT string to be saved // Helper function to get the NBT string to be saved
// If item is a placeholder, get original NBT; otherwise, get current NBT // If item is a placeholder, get original NBT; otherwise, get current NBT
private static String getNbtForStorage(ItemStack itemStack) { private static String getNbtForStorage(ItemStack itemStack) {
if (itemStack.is(Items.PAPER) && itemStack.hasTag() && itemStack.getTag().contains("playersync:original_item_nbt", Tag.TAG_STRING)) { if (itemStack.is(Items.PAPER) && itemStack.getComponents().has(DataComponentTypes.ORIGINAL_ITEM_NBT.get())) {
// It's our placeholder, retrieve the original NBT string // It's our placeholder, retrieve the original NBT string
return itemStack.getTag().getString("playersync:original_item_nbt"); return itemStack.getComponents().get(DataComponentTypes.ORIGINAL_ITEM_NBT.get());
} else { } else {
// It's a normal item or empty, serialize its current NBT // It's a normal item or empty, serialize its current NBT
return serialize(serializeNBT(itemStack).toString()); return serialize(serializeNBT(itemStack).toString());
@ -451,8 +455,9 @@ public class VanillaSync {
return new CompoundTag(); return new CompoundTag();
} }
// Serialize the ItemStack to NBT // Serialize the ItemStack to NBT
HolderLookup.Provider provider = ServerLifecycleHooks.getCurrentServer().registryAccess();
CompoundTag compoundTag = new CompoundTag(); CompoundTag compoundTag = new CompoundTag();
itemStack.save(compoundTag); itemStack.save(provider);
return compoundTag; return compoundTag;
} }
@ -494,18 +499,18 @@ public class VanillaSync {
} }
// Effects // Effects
Map<MobEffect, MobEffectInstance> effects = player.getActiveEffectsMap(); Map<Holder<MobEffect>, MobEffectInstance> effects = player.getActiveEffectsMap();
Map<Integer, String> effectMap = new HashMap<>(); Map<Integer, String> effectMap = new HashMap<>();
for (Map.Entry<MobEffect, MobEffectInstance> entry : effects.entrySet()) { for (Map.Entry<Holder<MobEffect>, MobEffectInstance> entry : effects.entrySet()) {
CompoundTag effectTag = entry.getValue().save(new CompoundTag()); Tag effectTag = entry.getValue().save();
effectMap.put(BuiltInRegistries.MOB_EFFECT.getId(entry.getKey()), serialize(effectTag.toString())); effectMap.put(BuiltInRegistries.MOB_EFFECT.getId(entry.getKey().value()), serialize(effectTag.toString()));
} }
// Advancements // Advancements
File advancements = null; File advancements = null;
byte[] advancementBytes = new byte[0]; byte[] advancementBytes = new byte[0];
if (JdbcConfig.SYNC_ADVANCEMENTS.get()) { if (JdbcConfig.SYNC_ADVANCEMENTS.get()) {
File gameDir = Objects.requireNonNull(player.getServer()).getServerDirectory(); File gameDir = Objects.requireNonNull(player.getServer()).getServerDirectory().toFile();
final MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); final MinecraftServer server = ServerLifecycleHooks.getCurrentServer();
if (server != null && server.isDedicatedServer() ) { if (server != null && server.isDedicatedServer() ) {
PlayerSync.LOGGER.trace("Reading dedicated server advancements"); PlayerSync.LOGGER.trace("Reading dedicated server advancements");
@ -576,7 +581,7 @@ public class VanillaSync {
static int tick = 0; static int tick = 0;
@SubscribeEvent @SubscribeEvent
public static void onUpdate(TickEvent.LevelTickEvent event) throws SQLException { public static void onUpdate(LevelTickEvent event) throws SQLException {
tick++; tick++;
if (tick == 1800) { if (tick == 1800) {
tick = 0; tick = 0;
@ -592,37 +597,35 @@ public class VanillaSync {
//AutoSave //AutoSave
@SubscribeEvent @SubscribeEvent
public static void onServerTick(TickEvent.ServerTickEvent event) { public static void onServerTick(ServerTickEvent.Post event) {
// Run at the end phase to avoid interfering with game logic // Run at the end phase to avoid interfering with game logic
if (event.phase == TickEvent.Phase.END) { autoSaveTickCounter++;
autoSaveTickCounter++; if (autoSaveTickCounter >= AUTO_SAVE_INTERVAL_TICKS) {
if (autoSaveTickCounter >= AUTO_SAVE_INTERVAL_TICKS) { autoSaveTickCounter = 0;
autoSaveTickCounter = 0; // Retrieve the current server instance
// Retrieve the current server instance MinecraftServer server = ServerLifecycleHooks.getCurrentServer();
MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); if (server != null) {
if (server != null) { // Iterate through all online players
// Iterate through all online players for (ServerPlayer player : server.getPlayerList().getPlayers()) {
for (ServerPlayer player : server.getPlayerList().getPlayers()) { executorService.submit(() -> {
executorService.submit(() -> { try {
try { // Call the same store method used in logout and file save events.
// Call the same store method used in logout and file save events. store(player, false);
store(player, false); } catch (Exception e) {
} catch (Exception e) { PlayerSync.LOGGER.error("Error auto-saving player " + player.getUUID(), e);
PlayerSync.LOGGER.error("Error auto-saving player " + player.getUUID(), e); }
} });
}); executorService.submit(() -> {
executorService.submit(() -> { try {
try { new ModsSupport().StoreCurios(player, false);
new ModsSupport().StoreCurios(player, false); } catch (SQLException e) {
} catch (SQLException e) { PlayerSync.LOGGER.error("Error auto-saving Curios data for player " + player.getUUID(), e);
PlayerSync.LOGGER.error("Error auto-saving Curios data for player " + player.getUUID(), e); }
} });
});
} }
} }
} }
}
} }
private static void setXpForPlayer(ServerPlayer serverPlayer, int databaseXp) { private static void setXpForPlayer(ServerPlayer serverPlayer, int databaseXp) {