diff --git a/pom.xml b/pom.xml index 860415c..3885d39 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ to.us.tf DeathSpectating - 1.1.3 + 1.2 1.8 1.8 diff --git a/src/main/java/to/us/tf/DeathSpectating/CompatUtil.java b/src/main/java/to/us/tf/DeathSpectating/CompatUtil.java deleted file mode 100644 index d90d0ec..0000000 --- a/src/main/java/to/us/tf/DeathSpectating/CompatUtil.java +++ /dev/null @@ -1,44 +0,0 @@ -package to.us.tf.DeathSpectating; - -import org.bukkit.Bukkit; - -/** - * Created on 2/27/2017. - * - * @author RoboMWM - */ -public class CompatUtil -{ - private static Integer serverVersion = null; - private static int currentVersion = 11; - public static boolean isNewer() - { - return getVersion() > currentVersion; - } - - public static int getVersion() - { - if (serverVersion != null) - return serverVersion; - String version = Bukkit.getBukkitVersion(); - version = version.substring(2); - version = version.substring(0, version.indexOf(".")); - int versionNumber; - try - { - versionNumber = Integer.valueOf(version); - } - catch (Exception e) - { - Bukkit.getLogger().warning("[DeathSpectating] Was not able to determine bukkit version."); - return -1; - } - serverVersion = versionNumber; - return versionNumber; - } - - public static boolean isOlder(int version) - { - return getVersion() < version; - } -} diff --git a/src/main/java/to/us/tf/DeathSpectating/DeathSpectating.java b/src/main/java/to/us/tf/DeathSpectating/DeathSpectating.java index f1c07c4..939c679 100644 --- a/src/main/java/to/us/tf/DeathSpectating/DeathSpectating.java +++ b/src/main/java/to/us/tf/DeathSpectating/DeathSpectating.java @@ -5,10 +5,10 @@ import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Particle; +import org.bukkit.Sound; +import org.bukkit.SoundCategory; import org.bukkit.Statistic; -import org.bukkit.World; import org.bukkit.enchantments.Enchantment; -import org.bukkit.entity.Creature; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.ExperienceOrb; @@ -24,7 +24,6 @@ import org.bukkit.metadata.FixedMetadataValue; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.potion.PotionEffect; -import org.bukkit.scheduler.BukkitRunnable; import to.us.tf.DeathSpectating.events.DeathSpectatingEvent; import to.us.tf.DeathSpectating.features.Titles; import to.us.tf.DeathSpectating.listeners.DamageListener; @@ -32,7 +31,9 @@ import to.us.tf.DeathSpectating.tasks.SpectateTask; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.logging.Level; /** @@ -49,8 +50,7 @@ public void onEnable() getServer().getPluginManager().registerEvents(this, this); getServer().getPluginManager().registerEvents(new DamageListener(this), this); getServer().getPluginManager().registerEvents(new MiscListeners(this), this); - if (!CompatUtil.isOlder(11)) //TODO: register in class, not in main(?) - getServer().getPluginManager().registerEvents(new Titles(this, configManager), this); + getServer().getPluginManager().registerEvents(new Titles(this, configManager), this); } public ConfigManager getConfigManager() @@ -82,7 +82,7 @@ public void setSpectating(Player player, boolean spectate, GameMode gameMode) player.removeMetadata("DEAD", this); player.setLastDamageCause(null); player.setGameMode(getServer().getDefaultGameMode()); - player.setFlySpeed(0.2f); + player.setFlySpeed(0.1f); } } @@ -144,9 +144,10 @@ public boolean startDeathSpectating(Player player) { /*Set spectating attributes*/ //Player#isDead() == true when PlayerDeathEvent is fired. + //Also prevents any potential to pickup anything that's dropped. setSpectating(player, true, player.getGameMode()); - /*Start Death simulation*/ + /*Start Death Event simulation*/ boolean keepInventory = Boolean.valueOf(player.getWorld().getGameRuleValue("keepInventory")); boolean showDeathMessages = Boolean.valueOf(player.getWorld().getGameRuleValue("showDeathMessages")); @@ -171,9 +172,10 @@ public boolean startDeathSpectating(Player player) //TODO: Non-vanilla behavior, see issue #4 String deathMessage = ""; - /*Fire PlayerDeathEvent*/ + /*Prepare PlayerDeathEvent*/ PlayerDeathEvent deathEvent = new PlayerDeathEvent(player, itemsToDrop, expToDrop, deathMessage); deathEvent.setKeepInventory(keepInventory); //CB's constructor does indeed set whether the inventory is kept or not, using the gamerule's value + //And fire getServer().getPluginManager().callEvent(deathEvent); //TODO: Non-vanilla behavior, see issue #5 @@ -181,7 +183,7 @@ public boolean startDeathSpectating(Player player) if (deathEvent.getDeathMessage() != null && !deathEvent.getDeathMessage().isEmpty() && showDeathMessages) getServer().broadcastMessage(deathEvent.getDeathMessage()); - //Clear and drop items + //Clear and drop items if keepInventory == false if (!deathEvent.getKeepInventory()) { player.getInventory().clear(); @@ -212,14 +214,22 @@ public boolean startDeathSpectating(Player player) player.incrementStatistic(Statistic.DEATHS); player.setStatistic(Statistic.TIME_SINCE_DEATH, 0); + //Clear potion effects TODO: do this before firing death event? + for (PotionEffect potionEffect : player.getActivePotionEffects()) + player.removePotionEffect(potionEffect.getType()); + //TODO: Non-vanilla behavior: Player death animation (red and falling over) (Issue #13) //Smoke effect //TODO: after 20 ticks (Issue #14) (Will implement 20 tick delay after issue #13 is resolved if (isSpectating(player)) //TODO: does smoke effect/death animation occur if player#spigot()#respawn() is called on death? My guess is no. - player.getWorld().spawnParticle(Particle.CLOUD, player.getLocation(), 25); - - //Clear potion effects - for (PotionEffect potionEffect : player.getActivePotionEffects()) - player.removePotionEffect(potionEffect.getType()); + player.getWorld().spawnParticle(Particle.CLOUD, player.getLocation(), 25, 1, 0.5, 1, 0.001); + + //Play the "death" sound (to all other players except the killed player; vanilla (spigot?) behavior). + //fyi, default resource pack doesn't have a different sound for this; only custom resource packs make use of this. + //TODO: distance check? + Set players = new HashSet<>(player.getWorld().getPlayers()); + players.remove(player); + for (Player p : players) + p.playSound(player.getLocation(), Sound.ENTITY_PLAYER_DEATH, SoundCategory.PLAYERS, 1.0f, 1.0f); /* End Death simulation*/ diff --git a/src/main/java/to/us/tf/DeathSpectating/listeners/DamageListener.java b/src/main/java/to/us/tf/DeathSpectating/listeners/DamageListener.java index 1215080..0403552 100644 --- a/src/main/java/to/us/tf/DeathSpectating/listeners/DamageListener.java +++ b/src/main/java/to/us/tf/DeathSpectating/listeners/DamageListener.java @@ -1,15 +1,15 @@ package to.us.tf.DeathSpectating.listeners; import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.SoundCategory; import org.bukkit.entity.EntityType; 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 org.bukkit.inventory.Inventory; import org.bukkit.inventory.PlayerInventory; -import to.us.tf.DeathSpectating.CompatUtil; import to.us.tf.DeathSpectating.DeathSpectating; /** @@ -42,15 +42,8 @@ void onPlayerBasicallyWouldBeDead(EntityDamageEvent event) //Ignore if player is holding a totem of undying PlayerInventory inventory = player.getInventory(); - try - { - if (inventory.getItemInMainHand().getType() == Material.TOTEM || inventory.getItemInOffHand().getType() == Material.TOTEM) - return; - } - catch (NoSuchFieldError | NoSuchMethodError e) //TOTEM (not in 1.10 and below) //getItemInMainHand, etc. (not in 1.8 and below) - { - if (CompatUtil.isNewer()) throw e; - } + if (inventory.getItemInMainHand().getType() == Material.TOTEM || inventory.getItemInOffHand().getType() == Material.TOTEM) + return; //Ignore if this is probably the result of the Essentials suicide command //Essentials will perform Player#setHealth(0), which does not fire a damage event, but does kill the player. This will lead to a double death message. @@ -59,11 +52,17 @@ void onPlayerBasicallyWouldBeDead(EntityDamageEvent event) return; player.setLastDamageCause(event); - //TODO: fire EntityResurrectEvent + //TODO: fire EntityResurrectEvent(?) /*Put player in death spectating mode*/ if (instance.startDeathSpectating(player)) + { //Cancel event so player doesn't actually die event.setCancelled(true); + + //Play the "hit" sound (since we canceled the event, the hit sound will not play) + player.getWorld().playSound(player.getLocation(), Sound.ENTITY_PLAYER_HURT, SoundCategory.PLAYERS, 1.0f, 1.0f); + } + } }