diff --git a/src/main/java/org/kapelle/hardcore_revive/HardcoreRevive.java b/src/main/java/org/kapelle/hardcore_revive/HardcoreRevive.java index 3962afa..8386ad4 100644 --- a/src/main/java/org/kapelle/hardcore_revive/HardcoreRevive.java +++ b/src/main/java/org/kapelle/hardcore_revive/HardcoreRevive.java @@ -4,11 +4,13 @@ import org.bukkit.plugin.java.JavaPlugin; public class HardcoreRevive extends JavaPlugin { DropHead dropHead; + SummonHead summonHead; @Override public void onEnable() { this.getLogger().info("hardcore-revive plugin enabled"); dropHead = new DropHead(this); + summonHead = new SummonHead(this); } } \ No newline at end of file diff --git a/src/main/java/org/kapelle/hardcore_revive/SummonHead.java b/src/main/java/org/kapelle/hardcore_revive/SummonHead.java new file mode 100644 index 0000000..e9eaaa5 --- /dev/null +++ b/src/main/java/org/kapelle/hardcore_revive/SummonHead.java @@ -0,0 +1,111 @@ +package org.kapelle.hardcore_revive; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Particle; +import org.bukkit.block.Block; +import org.bukkit.block.Sign; +import org.bukkit.block.Skull; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.SkullMeta; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.util.Vector; + +public class SummonHead implements Listener { + private final JavaPlugin plugin; + + public SummonHead(JavaPlugin plugin){ + this.plugin = plugin; + plugin.getServer().getPluginManager().registerEvents(this, plugin); + } + + @EventHandler + public void onBlockPlace(BlockPlaceEvent event){ + if(event.getBlockPlaced().getType() == Material.SOUL_CAMPFIRE && !event.isCancelled()){ + if (isValidMultiblock(event.getBlockPlaced().getLocation())){ + summonHead(event.getBlockPlaced().getLocation()); + } + } + } + + /** + * Checks if a block type is a sign that is standing (not mounted on a wall) + * @param block + * @return + */ + private boolean isStandingSign(Material block){ + return block == Material.SPRUCE_SIGN + || block == Material.ACACIA_SIGN + || block == Material.BIRCH_SIGN + || block == Material.CRIMSON_SIGN + || block == Material.DARK_OAK_SIGN + || block == Material.JUNGLE_SIGN + || block == Material.OAK_SIGN + || block == Material.WARPED_SIGN; + } + + /** + * Checks if the last placed block is a valid multiblock. + * The valid structure is from top to bottom: Standing sign, soul sand, soul campfire, soul sand + * @param lastBlockLocation Exprected to be the soul campfire + * @return if the structure is valid + */ + private boolean isValidMultiblock(Location lastBlockLocation){ + return lastBlockLocation.clone().add(new Vector(0,-1,0)).getBlock().getType() == Material.SOUL_SAND + && lastBlockLocation.clone().add(new Vector(0,1,0)).getBlock().getType() == Material.SOUL_SAND + && isStandingSign(lastBlockLocation.clone().add(new Vector(0,2,0)).getBlock().getType()); + + } + + /** + * Perform the head summoning ritual. + * @param lastBlockLocation The location of the core block of the multiblock structure. In this case + * the soul campfire. + */ + private void summonHead(Location lastBlockLocation){ + Block topBlock = lastBlockLocation.clone().add(new Vector(0,2,0)).getBlock(); + + String spiritName = getSignText((Sign) topBlock.getState()); + Player spirit = plugin.getServer().getPlayerExact(spiritName); + + if (spirit == null) { + // TODO: inform player about spirit not readchable (must be online) + return; + } + + // Remove sign + topBlock.setType(Material.AIR); + + // Spawn particle at sign + topBlock.getWorld().spawnParticle(Particle.SPELL_WITCH,topBlock.getLocation(),20); + + // Prepare head to be spawned + ItemStack head = new ItemStack(Material.PLAYER_HEAD); + SkullMeta headMeta = (SkullMeta) head.getItemMeta(); + assert headMeta != null; + headMeta.setOwningPlayer(spirit); + head.setItemMeta(headMeta); + + // Spawn head at the position of the sign + lastBlockLocation.getWorld().dropItem(topBlock.getLocation(),head); + + // Remove soul campfire + // FIXME: removing the campfire raises an execption somewhere else. But i think its fine. Maybe removing a tile entity works different + lastBlockLocation.getBlock().setType(Material.AIR); + } + + /** + * Joins all lines from a sign. That way usernames that are too long for a single line can fit. + * @param sign + * @return + */ + private String getSignText(Sign sign){ + return String.join("",sign.getLines()); + } + +}