From d1c95030f001ab7fe5326a673efb4a0e48726c7f Mon Sep 17 00:00:00 2001
From: William
Date: Thu, 4 Aug 2022 17:48:16 +0100
Subject: [PATCH] Added config option for syncing dead player inventories,
cancel damage if locked
---
.../husksync/listener/BukkitEventListener.java | 8 ++++++++
.../husksync/player/BukkitPlayer.java | 7 ++++++-
.../husksync/api/BaseHuskSyncAPI.java | 7 ++++---
.../william278/husksync/config/Settings.java | 1 +
.../husksync/listener/EventListener.java | 11 ++++++-----
.../william278/husksync/player/OnlineUser.java | 18 +++++++++++++++---
common/src/main/resources/config.yml | 1 +
7 files changed, 41 insertions(+), 12 deletions(-)
diff --git a/bukkit/src/main/java/net/william278/husksync/listener/BukkitEventListener.java b/bukkit/src/main/java/net/william278/husksync/listener/BukkitEventListener.java
index 6609c2f7..ea5e26b1 100644
--- a/bukkit/src/main/java/net/william278/husksync/listener/BukkitEventListener.java
+++ b/bukkit/src/main/java/net/william278/husksync/listener/BukkitEventListener.java
@@ -14,6 +14,7 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
+import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityPickupItemEvent;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
@@ -121,6 +122,13 @@ public class BukkitEventListener extends EventListener implements Listener {
}
}
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void onPlayerTakeDamage(@NotNull EntityDamageEvent event) {
+ if (event.getEntity() instanceof Player player) {
+ event.setCancelled(cancelPlayerEvent(BukkitPlayer.adapt(player)));
+ }
+ }
+
@EventHandler(ignoreCancelled = true)
public void onPlayerDeath(PlayerDeathEvent event) {
if (cancelPlayerEvent(BukkitPlayer.adapt(event.getEntity()))) {
diff --git a/bukkit/src/main/java/net/william278/husksync/player/BukkitPlayer.java b/bukkit/src/main/java/net/william278/husksync/player/BukkitPlayer.java
index 05582fdf..d835d07f 100644
--- a/bukkit/src/main/java/net/william278/husksync/player/BukkitPlayer.java
+++ b/bukkit/src/main/java/net/william278/husksync/player/BukkitPlayer.java
@@ -97,7 +97,7 @@ public class BukkitPlayer extends OnlineUser {
final double currentHealth = player.getHealth();
if (statusData.health != currentHealth) {
final double healthToSet = currentHealth > currentMaxHealth ? currentMaxHealth : statusData.health;
- if (healthToSet <= 0) {
+ if (healthToSet < 1) {
Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(), () -> player.setHealth(healthToSet));
} else {
player.setHealth(healthToSet);
@@ -572,6 +572,11 @@ public class BukkitPlayer extends OnlineUser {
});
}
+ @Override
+ public boolean isDead() {
+ return player.getHealth() < 1;
+ }
+
@Override
public void sendActionBar(@NotNull MineDown mineDown) {
player.spigot().sendMessage(ChatMessageType.ACTION_BAR, mineDown.replace().toComponent());
diff --git a/common/src/main/java/net/william278/husksync/api/BaseHuskSyncAPI.java b/common/src/main/java/net/william278/husksync/api/BaseHuskSyncAPI.java
index 3827e8c6..73b878b2 100644
--- a/common/src/main/java/net/william278/husksync/api/BaseHuskSyncAPI.java
+++ b/common/src/main/java/net/william278/husksync/api/BaseHuskSyncAPI.java
@@ -72,7 +72,7 @@ public abstract class BaseHuskSyncAPI {
public final CompletableFuture> getUserData(@NotNull User user) {
return CompletableFuture.supplyAsync(() -> {
if (user instanceof OnlineUser) {
- return ((OnlineUser) user).getUserData(plugin.getLoggingAdapter()).join();
+ return ((OnlineUser) user).getUserData(plugin.getLoggingAdapter(), plugin.getSettings()).join();
} else {
return plugin.getDatabase().getCurrentUserData(user).join().map(UserDataSnapshot::userData);
}
@@ -103,8 +103,9 @@ public abstract class BaseHuskSyncAPI {
* @since 2.0
*/
public final CompletableFuture saveUserData(@NotNull OnlineUser user) {
- return CompletableFuture.runAsync(() -> user.getUserData(plugin.getLoggingAdapter()).thenAccept(optionalUserData -> optionalUserData.ifPresent(
- userData -> plugin.getDatabase().setUserData(user, userData, DataSaveCause.API).join())));
+ return CompletableFuture.runAsync(() -> user.getUserData(plugin.getLoggingAdapter(), plugin.getSettings())
+ .thenAccept(optionalUserData -> optionalUserData.ifPresent(
+ userData -> plugin.getDatabase().setUserData(user, userData, DataSaveCause.API).join())));
}
/**
diff --git a/common/src/main/java/net/william278/husksync/config/Settings.java b/common/src/main/java/net/william278/husksync/config/Settings.java
index 5182630c..cf171028 100644
--- a/common/src/main/java/net/william278/husksync/config/Settings.java
+++ b/common/src/main/java/net/william278/husksync/config/Settings.java
@@ -144,6 +144,7 @@ public class Settings {
SYNCHRONIZATION_SAVE_ON_WORLD_SAVE("synchronization.save_on_world_save", OptionType.BOOLEAN, true),
SYNCHRONIZATION_COMPRESS_DATA("synchronization.compress_data", OptionType.BOOLEAN, true),
SYNCHRONIZATION_NETWORK_LATENCY_MILLISECONDS("synchronization.network_latency_milliseconds", OptionType.INTEGER, 500),
+ SYNCHRONIZATION_SAVE_DEAD_PLAYER_INVENTORIES("synchronization.save_dead_player_inventories", OptionType.BOOLEAN, true),
SYNCHRONIZATION_SYNC_INVENTORIES("synchronization.features.inventories", OptionType.BOOLEAN, true),
SYNCHRONIZATION_SYNC_ENDER_CHESTS("synchronization.features.ender_chests", OptionType.BOOLEAN, true),
SYNCHRONIZATION_SYNC_HEALTH("synchronization.features.health", OptionType.BOOLEAN, true),
diff --git a/common/src/main/java/net/william278/husksync/listener/EventListener.java b/common/src/main/java/net/william278/husksync/listener/EventListener.java
index 4370ed65..b2300a60 100644
--- a/common/src/main/java/net/william278/husksync/listener/EventListener.java
+++ b/common/src/main/java/net/william278/husksync/listener/EventListener.java
@@ -152,9 +152,10 @@ public abstract class EventListener {
// Handle asynchronous disconnection
lockedPlayers.add(user.uuid);
CompletableFuture.runAsync(() -> plugin.getRedisManager().setUserServerSwitch(user)
- .thenRun(() -> user.getUserData(plugin.getLoggingAdapter()).thenAccept(optionalUserData ->
- optionalUserData.ifPresent(userData -> plugin.getRedisManager().setUserData(user, userData)
- .thenRun(() -> plugin.getDatabase().setUserData(user, userData, DataSaveCause.DISCONNECT)))))
+ .thenRun(() -> user.getUserData(plugin.getLoggingAdapter(), plugin.getSettings()).thenAccept(
+ optionalUserData -> optionalUserData.ifPresent(userData -> plugin.getRedisManager()
+ .setUserData(user, userData).thenRun(() -> plugin.getDatabase()
+ .setUserData(user, userData, DataSaveCause.DISCONNECT)))))
.thenRun(() -> lockedPlayers.remove(user.uuid)).exceptionally(throwable -> {
plugin.getLoggingAdapter().log(Level.SEVERE,
"An exception occurred handling a player disconnection");
@@ -172,7 +173,7 @@ public abstract class EventListener {
if (disabling || !plugin.getSettings().getBooleanValue(Settings.ConfigOption.SYNCHRONIZATION_SAVE_ON_WORLD_SAVE)) {
return;
}
- usersInWorld.forEach(user -> user.getUserData(plugin.getLoggingAdapter()).join().ifPresent(
+ usersInWorld.forEach(user -> user.getUserData(plugin.getLoggingAdapter(), plugin.getSettings()).join().ifPresent(
userData -> plugin.getDatabase().setUserData(user, userData, DataSaveCause.WORLD_SAVE).join()));
}
@@ -217,7 +218,7 @@ public abstract class EventListener {
disabling = true;
plugin.getOnlineUsers().stream().filter(user -> !lockedPlayers.contains(user.uuid)).forEach(
- user -> user.getUserData(plugin.getLoggingAdapter()).join().ifPresent(
+ user -> user.getUserData(plugin.getLoggingAdapter(), plugin.getSettings()).join().ifPresent(
userData -> plugin.getDatabase().setUserData(user, userData, DataSaveCause.SERVER_SHUTDOWN).join()));
plugin.getDatabase().close();
diff --git a/common/src/main/java/net/william278/husksync/player/OnlineUser.java b/common/src/main/java/net/william278/husksync/player/OnlineUser.java
index f285d5e7..d3e08903 100644
--- a/common/src/main/java/net/william278/husksync/player/OnlineUser.java
+++ b/common/src/main/java/net/william278/husksync/player/OnlineUser.java
@@ -260,16 +260,28 @@ public abstract class OnlineUser extends User {
*/
public abstract void showMenu(@NotNull ItemEditorMenu menu);
+ /**
+ * Returns true if the player is dead
+ *
+ * @return true if the player is dead
+ */
+ public abstract boolean isDead();
+
/**
* Get the player's current {@link UserData} in an {@link Optional}
- *
+ *
+ * If the {@code SYNCHRONIZATION_SAVE_DEAD_PLAYER_INVENTORIES} ConfigOption has been set,
+ * the user's inventory will only be returned if they are alive
+ *
* If the user data could not be returned due to an exception, the optional will return empty
*
* @param logger The logger to use for handling exceptions
* @return the player's current {@link UserData} in an optional; empty if an exception occurs
*/
- public final CompletableFuture> getUserData(@NotNull Logger logger) {
- return CompletableFuture.supplyAsync(() -> Optional.of(new UserData(getStatus().join(), getInventory().join(),
+ public final CompletableFuture> getUserData(@NotNull Logger logger, @NotNull Settings settings) {
+ return CompletableFuture.supplyAsync(() -> Optional.of(new UserData(getStatus().join(),
+ (settings.getBooleanValue(Settings.ConfigOption.SYNCHRONIZATION_SAVE_DEAD_PLAYER_INVENTORIES)
+ ? getInventory().join() : (isDead() ? new ItemData("") : getInventory().join())),
getEnderChest().join(), getPotionEffects().join(), getAdvancements().join(),
getStatistics().join(), getLocation().join(), getPersistentDataContainer().join(),
getMinecraftVersion().toString())))
diff --git a/common/src/main/resources/config.yml b/common/src/main/resources/config.yml
index 542f4fde..5d8ac465 100644
--- a/common/src/main/resources/config.yml
+++ b/common/src/main/resources/config.yml
@@ -38,6 +38,7 @@ synchronization:
max_user_data_snapshots: 5
save_on_world_save: true
compress_data: true
+ save_dead_player_inventories: true
network_latency_milliseconds: 500
features:
inventories: true