diff --git a/src/main/java/fr/korastrip/paperplugin/SharedStats.java b/src/main/java/fr/korastrip/paperplugin/SharedStats.java index f1c6bd5..aeffa18 100644 --- a/src/main/java/fr/korastrip/paperplugin/SharedStats.java +++ b/src/main/java/fr/korastrip/paperplugin/SharedStats.java @@ -27,6 +27,7 @@ public void onEnable() { this.getServer().getPluginManager().registerEvents(new PlayerDeathListener(this), this); this.getServer().getPluginManager().registerEvents(new RegenerationListener(this), this); this.getServer().getPluginManager().registerEvents(new PlayerRespawnListener(this), this); + this.getServer().getPluginManager().registerEvents(new EntityResurrectListener(this), this); this.getLifecycleManager().registerEventHandler( LifecycleEvents.COMMANDS, diff --git a/src/main/java/fr/korastrip/paperplugin/listener/DamageListener.java b/src/main/java/fr/korastrip/paperplugin/listener/DamageListener.java index c8539ca..eadc2d4 100644 --- a/src/main/java/fr/korastrip/paperplugin/listener/DamageListener.java +++ b/src/main/java/fr/korastrip/paperplugin/listener/DamageListener.java @@ -2,19 +2,14 @@ import fr.korastrip.paperplugin.SharedStats; import fr.korastrip.paperplugin.model.SharedGroup; -import fr.korastrip.paperplugin.services.TotemService; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.kyori.adventure.title.Title; +import fr.korastrip.paperplugin.services.SharedHealthService; import org.bukkit.Bukkit; -import org.bukkit.Sound; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityDamageEvent; -import java.util.List; - public class DamageListener implements Listener { private final SharedStats plugin; @@ -23,7 +18,7 @@ public DamageListener(SharedStats plugin) { this.plugin = plugin; } - @EventHandler(ignoreCancelled = true) + @EventHandler public void onDamageReceive(EntityDamageEvent event) { if (event.getEntity() instanceof Player player) { @@ -34,67 +29,23 @@ public void onDamageReceive(EntityDamageEvent event) { if (group.isGroupDying) { event.setCancelled(true); - return; } + } + } - var finalDamage = event.getFinalDamage(); - event.setDamage(0); - - var newHealth = group.getHealth() - finalDamage; - - List players = group.getOnlinePlayers(); - - if (newHealth <= 0) { - - TotemService totemService = new TotemService(plugin); - - if(totemService.check()) { - totemService.applyEffect(); - return; - } - - group.isGroupDying = true; - - Bukkit.getScheduler().runTask( - plugin, - () -> { - if (group.getIsPlaying()) { - players.forEach(Player::kill); - } - } - ); - - final Component mainTitle = player.displayName() - .color(NamedTextColor.RED); - final Component subtitle = Component.text("is dead", NamedTextColor.WHITE); - final Title title = Title.title(mainTitle, subtitle); - - group.addPlayerDeath(player); - - players.forEach(p -> { - p.showTitle(title); - - p.playSound( - p.getLocation(), - Sound.ENTITY_WITHER_SPAWN, - 1.0f, - 1.0f - ); - }); - group.incrementsDeadCount(); - - return; - } + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onDamageApplied(EntityDamageEvent event) { + if (event.getEntity() instanceof Player player) { - group.setHealth(newHealth); - group.syncHealth(); - player.playHurtAnimation(0); + SharedGroup group = this.plugin.getGroup(); + if (!group.getIsPlaying()) return; + if (!group.getPlayersId().contains(player.getUniqueId())) return; - player.playSound( - player.getLocation(), - Sound.ENTITY_PLAYER_HURT, - 1.0f, - 1.0f + Bukkit.getScheduler().runTask(plugin, + () -> { + SharedHealthService sharedHealthService = new SharedHealthService(this.plugin); + sharedHealthService.shareLoss(); + } ); } } diff --git a/src/main/java/fr/korastrip/paperplugin/listener/EntityResurrectListener.java b/src/main/java/fr/korastrip/paperplugin/listener/EntityResurrectListener.java new file mode 100644 index 0000000..4ad934f --- /dev/null +++ b/src/main/java/fr/korastrip/paperplugin/listener/EntityResurrectListener.java @@ -0,0 +1,47 @@ +package fr.korastrip.paperplugin.listener; + +import fr.korastrip.paperplugin.SharedStats; +import fr.korastrip.paperplugin.model.SharedGroup; +import fr.korastrip.paperplugin.services.SharedHealthService; +import fr.korastrip.paperplugin.services.TotemService; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityResurrectEvent; + +public class EntityResurrectListener implements Listener { + + private final SharedStats plugin; + + public EntityResurrectListener(SharedStats plugin) { + this.plugin = plugin; + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onEntityResurrect(EntityResurrectEvent e) { + if (e.getEntity() instanceof Player player) { + + TotemService totemService = new TotemService(this.plugin); + SharedGroup group = this.plugin.getGroup(); + + if (!group.getIsPlaying()) return; + if (!group.getPlayersId().contains(player.getUniqueId())) return; + + if (group.isGroupDying) { + e.setCancelled(true); + return; + } + + if (!e.isCancelled()) { + totemService.applyEffect(); + } else if (totemService.check()) { + e.setCancelled(false); + totemService.applyEffect(); + } else { + SharedHealthService sharedHealthService = new SharedHealthService(this.plugin); + sharedHealthService.groupDeath(player); + } + } + } +} diff --git a/src/main/java/fr/korastrip/paperplugin/listener/PlayerDeathListener.java b/src/main/java/fr/korastrip/paperplugin/listener/PlayerDeathListener.java index 2de43fa..c12b39c 100644 --- a/src/main/java/fr/korastrip/paperplugin/listener/PlayerDeathListener.java +++ b/src/main/java/fr/korastrip/paperplugin/listener/PlayerDeathListener.java @@ -2,6 +2,7 @@ import fr.korastrip.paperplugin.SharedStats; import fr.korastrip.paperplugin.model.SharedGroup; +import fr.korastrip.paperplugin.services.SharedHealthService; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -24,6 +25,11 @@ public void onPlayerDeath(PlayerDeathEvent event) { if (!group.getIsPlaying()) return; if (!group.getPlayersId().contains(player.getUniqueId())) return; + if(!group.isGroupDying) { + SharedHealthService sharedHealthService = new SharedHealthService(this.plugin); + sharedHealthService.groupDeath(player); + } + Bukkit.getScheduler().runTaskLater( plugin, () -> { diff --git a/src/main/java/fr/korastrip/paperplugin/listener/RegenerationListener.java b/src/main/java/fr/korastrip/paperplugin/listener/RegenerationListener.java index 28b44c5..c801ec5 100644 --- a/src/main/java/fr/korastrip/paperplugin/listener/RegenerationListener.java +++ b/src/main/java/fr/korastrip/paperplugin/listener/RegenerationListener.java @@ -2,6 +2,7 @@ import fr.korastrip.paperplugin.SharedStats; import fr.korastrip.paperplugin.model.SharedGroup; +import fr.korastrip.paperplugin.services.SharedHealthService; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -23,6 +24,10 @@ public void onRegeneration(EntityRegainHealthEvent event) { if(group.getPlayersId().contains(player.getUniqueId()) && group.getIsPlaying()) { event.setCancelled(true); + SharedHealthService sharedHealthService = new SharedHealthService(this.plugin); + sharedHealthService.shareLoss(); + + if(group.isGroupDying) return; double healthAmount = event.getAmount(); diff --git a/src/main/java/fr/korastrip/paperplugin/model/SharedGroup.java b/src/main/java/fr/korastrip/paperplugin/model/SharedGroup.java index 04612fa..95b3773 100644 --- a/src/main/java/fr/korastrip/paperplugin/model/SharedGroup.java +++ b/src/main/java/fr/korastrip/paperplugin/model/SharedGroup.java @@ -113,7 +113,7 @@ public List getOnlinePlayers() { } public void syncHealth() { - this.getOnlinePlayers().forEach(p -> p.setHealth(this.getHealth())); + this.getOnlinePlayers().stream().filter(p -> !p.isDead()).forEach(p -> p.setHealth(this.getHealth())); } public void addPlayerDeath(Player player) { diff --git a/src/main/java/fr/korastrip/paperplugin/services/SharedHealthService.java b/src/main/java/fr/korastrip/paperplugin/services/SharedHealthService.java new file mode 100644 index 0000000..336d689 --- /dev/null +++ b/src/main/java/fr/korastrip/paperplugin/services/SharedHealthService.java @@ -0,0 +1,98 @@ +package fr.korastrip.paperplugin.services; + +import fr.korastrip.paperplugin.SharedStats; +import fr.korastrip.paperplugin.model.SharedGroup; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.title.Title; +import org.bukkit.Bukkit; +import org.bukkit.Sound; +import org.bukkit.entity.Damageable; +import org.bukkit.entity.Player; + +public class SharedHealthService { + + private final SharedStats plugin; + + public SharedHealthService(SharedStats plugin) { + this.plugin = plugin; + } + + + public void groupDeath(Player deathPlayer) { + SharedGroup group = this.plugin.getGroup(); + group.isGroupDying = true; + + var players = group.getOnlinePlayers(); + + Bukkit.getScheduler().runTask( + plugin, + () -> { + if (group.getIsPlaying()) { + group.getOnlinePlayers().stream().filter(p -> !p.isDead()).forEach(Damageable::kill); + } + } + ); + + final Component mainTitle = deathPlayer.displayName() + .color(NamedTextColor.RED); + final Component subtitle = Component.text("is dead", NamedTextColor.WHITE); + final Title title = Title.title(mainTitle, subtitle); + + group.addPlayerDeath(deathPlayer); + + players.forEach(p -> { + p.showTitle(title); + + p.playSound( + p.getLocation(), + Sound.ENTITY_WITHER_SPAWN, + 1.0f, + 1.0f + ); + }); + group.incrementsDeadCount(); + } + + public void shareLoss() { + SharedGroup group = this.plugin.getGroup(); + + if (!group.getIsPlaying() || group.isGroupDying) return; + + double totalLost = 0; + Player mostHurtPlayer = null; + double currentDamage = 0; + for (Player member : group.getOnlinePlayers()) { + if (member.isDead()) continue; + + // Players store health as a float: compare at the same precision to avoid fake losses. + double playerLost = (float) group.getHealth() - member.getHealth(); + if (playerLost > 0) { + totalLost += playerLost; + + if(playerLost > currentDamage) { + currentDamage = playerLost; + mostHurtPlayer = member; + } + + } + } + + if (totalLost == 0) return; + + var newHealth = group.getHealth() - totalLost; + + if (newHealth <= 0) { + TotemService totemService = new TotemService(this.plugin); + if (totemService.check()) { + totemService.applyEffect(); + } else { + this.groupDeath(mostHurtPlayer); + } + return; + } + + group.setHealth(newHealth); + group.syncHealth(); + } +}