mirror of
https://github.com/WiIIiam278/HuskSync.git
synced 2026-01-06 15:41:56 +00:00
Merge branch 'future/nms'
This commit is contained in:
@@ -16,6 +16,7 @@ import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
import java.util.*;
|
||||
|
||||
public class DataSerializer {
|
||||
@@ -207,17 +208,23 @@ public class DataSerializer {
|
||||
playerLocation.getYaw(), playerLocation.getPitch(), player.getWorld().getName(), player.getWorld().getEnvironment()));
|
||||
}
|
||||
|
||||
public record PlayerLocation(double x, double y, double z, float yaw, float pitch,
|
||||
String worldName, World.Environment environment) implements Serializable {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") // Ignore the unchecked cast here
|
||||
public static ArrayList<DataSerializer.AdvancementRecord> deserializeAdvancementData(String serializedAdvancementData) throws IOException {
|
||||
public static List<DataSerializer.AdvancementRecordDate> deserializeAdvancementData(String serializedAdvancementData) throws IOException {
|
||||
if (serializedAdvancementData.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
try {
|
||||
return (ArrayList<DataSerializer.AdvancementRecord>) RedisMessage.deserialize(serializedAdvancementData);
|
||||
List<?> deserialize = (List<?>) RedisMessage.deserialize(serializedAdvancementData);
|
||||
|
||||
if (!deserialize.isEmpty() && deserialize.get(0) instanceof AdvancementRecord) {
|
||||
deserialize = ((List<AdvancementRecord>) deserialize).stream()
|
||||
.map(o -> new AdvancementRecordDate(
|
||||
o.advancementKey,
|
||||
o.awardedAdvancementCriteria
|
||||
)).toList();
|
||||
}
|
||||
|
||||
return (List<AdvancementRecordDate>) deserialize;
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new IOException("Unable to decode class type.", e);
|
||||
}
|
||||
@@ -225,22 +232,21 @@ public class DataSerializer {
|
||||
|
||||
public static String getSerializedAdvancements(Player player) throws IOException {
|
||||
Iterator<Advancement> serverAdvancements = Bukkit.getServer().advancementIterator();
|
||||
ArrayList<DataSerializer.AdvancementRecord> advancementData = new ArrayList<>();
|
||||
ArrayList<DataSerializer.AdvancementRecordDate> advancementData = new ArrayList<>();
|
||||
|
||||
while (serverAdvancements.hasNext()) {
|
||||
final AdvancementProgress progress = player.getAdvancementProgress(serverAdvancements.next());
|
||||
final NamespacedKey advancementKey = progress.getAdvancement().getKey();
|
||||
final ArrayList<String> awardedCriteria = new ArrayList<>(progress.getAwardedCriteria());
|
||||
advancementData.add(new DataSerializer.AdvancementRecord(advancementKey.getNamespace() + ":" + advancementKey.getKey(), awardedCriteria));
|
||||
|
||||
final Map<String, Date> awardedCriteria = new HashMap<>();
|
||||
progress.getAwardedCriteria().forEach(s -> awardedCriteria.put(s, progress.getDateAwarded(s)));
|
||||
|
||||
advancementData.add(new DataSerializer.AdvancementRecordDate(advancementKey.getNamespace() + ":" + advancementKey.getKey(), awardedCriteria));
|
||||
}
|
||||
|
||||
return RedisMessage.serialize(advancementData);
|
||||
}
|
||||
|
||||
public record AdvancementRecord(String advancementKey,
|
||||
ArrayList<String> awardedAdvancementCriteria) implements Serializable {
|
||||
}
|
||||
|
||||
public static DataSerializer.StatisticData deserializeStatisticData(String serializedStatisticData) throws IOException {
|
||||
if (serializedStatisticData.isEmpty()) {
|
||||
return new DataSerializer.StatisticData(new HashMap<>(), new HashMap<>(), new HashMap<>(), new HashMap<>());
|
||||
@@ -288,6 +294,22 @@ public class DataSerializer {
|
||||
return RedisMessage.serialize(statisticData);
|
||||
}
|
||||
|
||||
public record PlayerLocation(double x, double y, double z, float yaw, float pitch,
|
||||
String worldName, World.Environment environment) implements Serializable {
|
||||
}
|
||||
|
||||
public record AdvancementRecord(String advancementKey,
|
||||
ArrayList<String> awardedAdvancementCriteria) implements Serializable {
|
||||
}
|
||||
|
||||
public record AdvancementRecordDate(String key, Map<String, Date> criteriaMap) implements Serializable {
|
||||
AdvancementRecordDate(String key, List<String> criteriaList) {
|
||||
this(key, new HashMap<>() {{
|
||||
criteriaList.forEach(s -> put(s, Date.from(Instant.EPOCH)));
|
||||
}});
|
||||
}
|
||||
}
|
||||
|
||||
public record StatisticData(HashMap<Statistic, Integer> untypedStatisticValues,
|
||||
HashMap<Statistic, HashMap<Material, Integer>> blockStatisticValues,
|
||||
HashMap<Statistic, HashMap<Material, Integer>> itemStatisticValues,
|
||||
|
||||
@@ -20,8 +20,6 @@ import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.time.Period;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
|
||||
@@ -160,7 +158,7 @@ public class PlayerSetter {
|
||||
// Set the player's data from the PlayerData
|
||||
try {
|
||||
if (Settings.syncAdvancements) {
|
||||
ArrayList<DataSerializer.AdvancementRecord> advancementRecords
|
||||
List<DataSerializer.AdvancementRecordDate> advancementRecords
|
||||
= DataSerializer.deserializeAdvancementData(data.getSerializedAdvancements());
|
||||
|
||||
if (Settings.useNativeImplementation) {
|
||||
@@ -171,7 +169,7 @@ public class PlayerSetter {
|
||||
plugin.getLogger().log(Level.WARNING,
|
||||
"Your server does not support a native implementation of achievements synchronization");
|
||||
plugin.getLogger().log(Level.WARNING,
|
||||
"Your server version {0}. Please disable using native implementation!", Bukkit.getVersion());
|
||||
"Your server version is {0}. Please disable using native implementation!", Bukkit.getVersion());
|
||||
|
||||
Settings.useNativeImplementation = false;
|
||||
setPlayerAdvancements(player, advancementRecords, data);
|
||||
@@ -280,16 +278,17 @@ public class PlayerSetter {
|
||||
}
|
||||
}
|
||||
|
||||
private static void nativeSyncPlayerAdvancements(final Player player, final List<DataSerializer.AdvancementRecord> advancementRecords) {
|
||||
private static void nativeSyncPlayerAdvancements(final Player player, final List<DataSerializer.AdvancementRecordDate> advancementRecords) {
|
||||
final Object playerAdvancements = AdvancementUtils.getPlayerAdvancements(player);
|
||||
|
||||
// Clear
|
||||
AdvancementUtils.clearPlayerAdvancementsMap(playerAdvancements);
|
||||
AdvancementUtils.clearPlayerAdvancements(playerAdvancements);
|
||||
AdvancementUtils.clearVisibleAdvancements(playerAdvancements);
|
||||
|
||||
advancementRecords.forEach(advancementRecord -> {
|
||||
NamespacedKey namespacedKey = Objects.requireNonNull(
|
||||
NamespacedKey.fromString(advancementRecord.advancementKey()),
|
||||
"Invalid Namespaced key of " + advancementRecord.advancementKey()
|
||||
NamespacedKey.fromString(advancementRecord.key()),
|
||||
"Invalid Namespaced key of " + advancementRecord.key()
|
||||
);
|
||||
|
||||
Advancement bukkitAdvancement = Bukkit.getAdvancement(namespacedKey);
|
||||
@@ -298,26 +297,21 @@ public class PlayerSetter {
|
||||
return;
|
||||
}
|
||||
|
||||
// todo: sync date of get advancement
|
||||
Date date = Date.from(Instant.now().minus(Period.ofWeeks(1)));
|
||||
|
||||
Object advancement = AdvancementUtils.getHandle(bukkitAdvancement);
|
||||
List<String> criteriaList = advancementRecord.awardedAdvancementCriteria();
|
||||
Map<String, Date> criteriaList = advancementRecord.criteriaMap();
|
||||
{
|
||||
Map<String, Object> nativeCriteriaMap = new HashMap<>();
|
||||
criteriaList.forEach(criteria ->
|
||||
criteriaList.forEach((criteria, date) ->
|
||||
nativeCriteriaMap.put(criteria, AdvancementUtils.newCriterionProgress(date))
|
||||
);
|
||||
Object nativeAdvancementProgress = AdvancementUtils.newAdvancementProgress(nativeCriteriaMap);
|
||||
|
||||
AdvancementUtils.startProgress(playerAdvancements, advancement, nativeAdvancementProgress);
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
synchronized (playerAdvancements) {
|
||||
AdvancementUtils.markPlayerAdvancementsFirst(playerAdvancements);
|
||||
AdvancementUtils.ensureAllVisible(playerAdvancements);
|
||||
AdvancementUtils.ensureAllVisible(playerAdvancements); // Set all completed advancement is visible
|
||||
AdvancementUtils.markPlayerAdvancementsFirst(playerAdvancements); // Mark the sending of visible advancement as the first
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,7 +321,7 @@ public class PlayerSetter {
|
||||
* @param player The player to set the advancements of
|
||||
* @param advancementData The ArrayList of {@link DataSerializer.AdvancementRecord}s to set
|
||||
*/
|
||||
private static void setPlayerAdvancements(Player player, ArrayList<DataSerializer.AdvancementRecord> advancementData, PlayerData data) {
|
||||
private static void setPlayerAdvancements(Player player, List<DataSerializer.AdvancementRecordDate> advancementData, PlayerData data) {
|
||||
// Temporarily disable advancement announcing if needed
|
||||
boolean announceAdvancementUpdate = false;
|
||||
if (Boolean.TRUE.equals(player.getWorld().getGameRuleValue(GameRule.ANNOUNCE_ADVANCEMENTS))) {
|
||||
@@ -345,13 +339,13 @@ public class PlayerSetter {
|
||||
boolean correctExperienceCheck = false; // Determines whether the experience might have changed warranting an update
|
||||
Advancement advancement = serverAdvancements.next();
|
||||
AdvancementProgress playerProgress = player.getAdvancementProgress(advancement);
|
||||
for (DataSerializer.AdvancementRecord record : advancementData) {
|
||||
for (DataSerializer.AdvancementRecordDate record : advancementData) {
|
||||
// If the advancement is one on the data
|
||||
if (record.advancementKey().equals(advancement.getKey().getNamespace() + ":" + advancement.getKey().getKey())) {
|
||||
if (record.key().equals(advancement.getKey().getNamespace() + ":" + advancement.getKey().getKey())) {
|
||||
|
||||
// Award all criteria that the player does not have that they do on the cache
|
||||
ArrayList<String> currentlyAwardedCriteria = new ArrayList<>(playerProgress.getAwardedCriteria());
|
||||
for (String awardCriteria : record.awardedAdvancementCriteria()) {
|
||||
for (String awardCriteria : record.criteriaMap().keySet()) {
|
||||
if (!playerProgress.getAwardedCriteria().contains(awardCriteria)) {
|
||||
Bukkit.getScheduler().runTask(plugin, () -> player.getAdvancementProgress(advancement).awardCriteria(awardCriteria));
|
||||
correctExperienceCheck = true;
|
||||
|
||||
@@ -9,19 +9,20 @@ import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class AdvancementUtils {
|
||||
|
||||
public final static Class<?> PLAYER_ADVANCEMENT;
|
||||
private final static Field PLAYER_ADVANCEMENTS_MAP;
|
||||
private final static Field PLAYER_VISIBLE_SET;
|
||||
private final static Field PLAYER_ADVANCEMENTS;
|
||||
private final static Field CRITERIA_MAP;
|
||||
private final static Field CRITERIA_DATE;
|
||||
private final static Field IS_FIRST_PACKET;
|
||||
|
||||
private final static Method GET_HANDLE;
|
||||
private final static Method START_PROGRESS;
|
||||
private final static Method ENSURE_ALL_VISIBLE;
|
||||
|
||||
private final static Class<?> ADVANCEMENT_PROGRESS;
|
||||
private final static Class<?> CRITERION_PROGRESS;
|
||||
|
||||
@@ -43,21 +44,24 @@ public class AdvancementUtils {
|
||||
|
||||
Class<?> ADVANCEMENT = ThrowSupplier.get(() -> Class.forName("net.minecraft.advancements.Advancement"));
|
||||
|
||||
Class<?> PLAYER_ADVANCEMENTS = MinecraftVersionUtils.getMinecraftClass("AdvancementDataPlayer");
|
||||
PLAYER_ADVANCEMENTS_MAP = ThrowSupplier.get(() -> PLAYER_ADVANCEMENTS.getDeclaredField("h"));
|
||||
PLAYER_ADVANCEMENT = MinecraftVersionUtils.getMinecraftClass("AdvancementDataPlayer");
|
||||
PLAYER_ADVANCEMENTS_MAP = ThrowSupplier.get(() -> PLAYER_ADVANCEMENT.getDeclaredField("h"));
|
||||
PLAYER_ADVANCEMENTS_MAP.setAccessible(true);
|
||||
|
||||
START_PROGRESS = ThrowSupplier.get(() -> PLAYER_ADVANCEMENTS.getDeclaredMethod("a", ADVANCEMENT, ADVANCEMENT_PROGRESS));
|
||||
PLAYER_VISIBLE_SET = ThrowSupplier.get(() -> PLAYER_ADVANCEMENT.getDeclaredField("i"));
|
||||
PLAYER_VISIBLE_SET.setAccessible(true);
|
||||
|
||||
START_PROGRESS = ThrowSupplier.get(() -> PLAYER_ADVANCEMENT.getDeclaredMethod("a", ADVANCEMENT, ADVANCEMENT_PROGRESS));
|
||||
START_PROGRESS.setAccessible(true);
|
||||
|
||||
ENSURE_ALL_VISIBLE = ThrowSupplier.get(() -> PLAYER_ADVANCEMENTS.getDeclaredMethod("c"));
|
||||
ENSURE_ALL_VISIBLE = ThrowSupplier.get(() -> PLAYER_ADVANCEMENT.getDeclaredMethod("c"));
|
||||
ENSURE_ALL_VISIBLE.setAccessible(true);
|
||||
|
||||
IS_FIRST_PACKET = ThrowSupplier.get(() -> PLAYER_ADVANCEMENTS.getDeclaredField("n"));
|
||||
IS_FIRST_PACKET = ThrowSupplier.get(() -> PLAYER_ADVANCEMENT.getDeclaredField("n"));
|
||||
IS_FIRST_PACKET.setAccessible(true);
|
||||
}
|
||||
|
||||
public static void markPlayerAdvancementsFirst(Object playerAdvancements) {
|
||||
public static void markPlayerAdvancementsFirst(final Object playerAdvancements) {
|
||||
try {
|
||||
IS_FIRST_PACKET.set(playerAdvancements, true);
|
||||
} catch (IllegalAccessException e) {
|
||||
@@ -74,7 +78,7 @@ public class AdvancementUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void clearPlayerAdvancementsMap(final Object playerAdvancement) {
|
||||
public static void clearPlayerAdvancements(final Object playerAdvancement) {
|
||||
try {
|
||||
((Map<?, ?>) PLAYER_ADVANCEMENTS_MAP.get(playerAdvancement))
|
||||
.clear();
|
||||
@@ -130,4 +134,12 @@ public class AdvancementUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void clearVisibleAdvancements(final Object playerAdvancements) {
|
||||
try {
|
||||
((Set<?>) PLAYER_VISIBLE_SET.get(playerAdvancements))
|
||||
.clear();
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user