mirror of
https://github.com/WiIIiam278/HuskSync.git
synced 2025-12-31 04:36:45 +00:00
Fix data sync when changing servers, consume keys when retrieved
This commit is contained in:
@@ -3,10 +3,8 @@ package net.william278.husksync.listener;
|
||||
import net.william278.husksync.BukkitHuskSync;
|
||||
import net.william278.husksync.player.BukkitPlayer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.event.world.WorldSaveEvent;
|
||||
@@ -32,7 +30,7 @@ public class BukkitEventListener extends EventListener implements Listener {
|
||||
BukkitPlayer.remove(event.getPlayer());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onWorldSave(@NotNull WorldSaveEvent event) {
|
||||
super.handleWorldSave(event.getWorld().getPlayers().stream().map(BukkitPlayer::adapt)
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
@@ -70,9 +70,10 @@ public class BukkitPlayer extends OnlineUser {
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> setStatus(@NotNull StatusData statusData,
|
||||
boolean setHealth, boolean setMaxHealth,
|
||||
boolean setHunger, boolean setExperience,
|
||||
boolean setGameMode, boolean setFlying) {
|
||||
final boolean setHealth, final boolean setMaxHealth,
|
||||
final boolean setHunger, final boolean setExperience,
|
||||
final boolean setGameMode, final boolean setFlying,
|
||||
final boolean setSelectedItemSlot) {
|
||||
return CompletableFuture.runAsync(() -> {
|
||||
double currentMaxHealth = Objects.requireNonNull(player.getAttribute(Attribute.GENERIC_MAX_HEALTH))
|
||||
.getBaseValue();
|
||||
@@ -101,20 +102,26 @@ public class BukkitPlayer extends OnlineUser {
|
||||
player.setSaturation(statusData.saturation);
|
||||
player.setExhaustion(statusData.saturationExhaustion);
|
||||
}
|
||||
if (setSelectedItemSlot) {
|
||||
player.getInventory().setHeldItemSlot(statusData.selectedItemSlot);
|
||||
}
|
||||
if (setExperience) {
|
||||
player.setTotalExperience(statusData.totalExperience);
|
||||
player.setLevel(statusData.expLevel);
|
||||
player.setExp(statusData.expProgress);
|
||||
}
|
||||
if (setGameMode) {
|
||||
player.setGameMode(GameMode.valueOf(statusData.gameMode));
|
||||
Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(), () ->
|
||||
player.setGameMode(GameMode.valueOf(statusData.gameMode)));
|
||||
}
|
||||
if (setFlying) {
|
||||
if (statusData.isFlying) {
|
||||
player.setAllowFlight(true);
|
||||
player.setFlying(true);
|
||||
}
|
||||
player.setFlying(false);
|
||||
Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(), () -> {
|
||||
if (statusData.isFlying) {
|
||||
player.setAllowFlight(true);
|
||||
player.setFlying(true);
|
||||
}
|
||||
player.setFlying(false);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -189,7 +196,8 @@ public class BukkitPlayer extends OnlineUser {
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> setAdvancements(@NotNull List<AdvancementData> advancementData) {
|
||||
return CompletableFuture.runAsync(() -> {
|
||||
return CompletableFuture.runAsync(() -> Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(), () -> {
|
||||
|
||||
// Temporarily disable advancement announcing if needed
|
||||
boolean announceAdvancementUpdate = false;
|
||||
if (Boolean.TRUE.equals(player.getWorld().getGameRuleValue(GameRule.ANNOUNCE_ADVANCEMENTS))) {
|
||||
@@ -205,50 +213,53 @@ public class BukkitPlayer extends OnlineUser {
|
||||
// Determines whether the experience might have changed warranting an update
|
||||
final AtomicBoolean correctExperience = new AtomicBoolean(false);
|
||||
|
||||
// Apply the advancements to the player
|
||||
final Iterator<Advancement> serverAdvancements = Bukkit.getServer().advancementIterator();
|
||||
while (serverAdvancements.hasNext()) {
|
||||
// Iterate through all advancements
|
||||
final Advancement advancement = serverAdvancements.next();
|
||||
final AdvancementProgress playerProgress = player.getAdvancementProgress(advancement);
|
||||
// Run asynchronously as advancement setting is expensive
|
||||
CompletableFuture.runAsync(() -> {
|
||||
// Apply the advancements to the player
|
||||
final Iterator<Advancement> serverAdvancements = Bukkit.getServer().advancementIterator();
|
||||
while (serverAdvancements.hasNext()) {
|
||||
// Iterate through all advancements
|
||||
final Advancement advancement = serverAdvancements.next();
|
||||
final AdvancementProgress playerProgress = player.getAdvancementProgress(advancement);
|
||||
|
||||
advancementData.stream().filter(record -> record.key.equals(advancement.getKey().toString())).findFirst().ifPresentOrElse(
|
||||
// Award all criteria that the player does not have that they do on the cache
|
||||
record -> {
|
||||
record.completedCriteria.keySet().stream()
|
||||
.filter(criterion -> !playerProgress.getAwardedCriteria().contains(criterion))
|
||||
.forEach(criterion -> {
|
||||
Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(),
|
||||
() -> player.getAdvancementProgress(advancement).awardCriteria(criterion));
|
||||
correctExperience.set(true);
|
||||
});
|
||||
advancementData.stream().filter(record -> record.key.equals(advancement.getKey().toString())).findFirst().ifPresentOrElse(
|
||||
// Award all criteria that the player does not have that they do on the cache
|
||||
record -> {
|
||||
record.completedCriteria.keySet().stream()
|
||||
.filter(criterion -> !playerProgress.getAwardedCriteria().contains(criterion))
|
||||
.forEach(criterion -> {
|
||||
Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(),
|
||||
() -> player.getAdvancementProgress(advancement).awardCriteria(criterion));
|
||||
correctExperience.set(true);
|
||||
});
|
||||
|
||||
// Revoke all criteria that the player does have but should not
|
||||
new ArrayList<>(playerProgress.getAwardedCriteria()).stream().filter(criterion -> !record.completedCriteria.containsKey(criterion))
|
||||
.forEach(criterion -> Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(),
|
||||
() -> player.getAdvancementProgress(advancement).revokeCriteria(criterion)));
|
||||
// Revoke all criteria that the player does have but should not
|
||||
new ArrayList<>(playerProgress.getAwardedCriteria()).stream().filter(criterion -> !record.completedCriteria.containsKey(criterion))
|
||||
.forEach(criterion -> Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(),
|
||||
() -> player.getAdvancementProgress(advancement).revokeCriteria(criterion)));
|
||||
|
||||
},
|
||||
// Revoke the criteria as the player shouldn't have any
|
||||
() -> new ArrayList<>(playerProgress.getAwardedCriteria()).forEach(criterion ->
|
||||
Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(),
|
||||
() -> player.getAdvancementProgress(advancement).revokeCriteria(criterion))));
|
||||
},
|
||||
// Revoke the criteria as the player shouldn't have any
|
||||
() -> new ArrayList<>(playerProgress.getAwardedCriteria()).forEach(criterion ->
|
||||
Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(),
|
||||
() -> player.getAdvancementProgress(advancement).revokeCriteria(criterion))));
|
||||
|
||||
// Update the player's experience in case the advancement changed that
|
||||
if (correctExperience.get()) {
|
||||
player.setLevel(experienceLevel);
|
||||
player.setExp(expProgress);
|
||||
correctExperience.set(false);
|
||||
// Update the player's experience in case the advancement changed that
|
||||
if (correctExperience.get()) {
|
||||
player.setLevel(experienceLevel);
|
||||
player.setExp(expProgress);
|
||||
correctExperience.set(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Re-enable announcing advancements (back on main thread again)
|
||||
Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(), () -> {
|
||||
if (finalAnnounceAdvancementUpdate) {
|
||||
player.getWorld().setGameRule(GameRule.ANNOUNCE_ADVANCEMENTS, true);
|
||||
}
|
||||
// Re-enable announcing advancements (back on main thread again)
|
||||
Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(), () -> {
|
||||
if (finalAnnounceAdvancementUpdate) {
|
||||
player.getWorld().setGameRule(GameRule.ANNOUNCE_ADVANCEMENTS, true);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -397,6 +408,16 @@ public class BukkitPlayer extends OnlineUser {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDead() {
|
||||
return player.isDead() || player.getHealth() <= 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOffline() {
|
||||
return player == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(@NotNull String node) {
|
||||
return player.hasPermission(node);
|
||||
|
||||
Reference in New Issue
Block a user