package com.nisovin.magicspells.spelleffects; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Entity; import org.bukkit.entity.Item; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import com.nisovin.magicspells.MagicSpells; import com.nisovin.magicspells.materials.MagicMaterial; import com.nisovin.magicspells.materials.MagicUnknownMaterial; import com.nisovin.magicspells.util.BlockUtils; import com.nisovin.magicspells.util.SpellAnimation; import com.nisovin.magicspells.util.Util; class NovaEffect extends SpellEffect { MagicMaterial mat; int radius = 3; int tickInterval = 5; @Override public void loadFromString(String string) { if (string != null && !string.isEmpty()) { String[] params = string.split(" "); int type = 51; byte data = 0; if (params.length >= 1) { try { type = Integer.parseInt(params[0]); } catch (NumberFormatException e) { } } if (params.length >= 2) { try { data = Byte.parseByte(params[1]); } catch (NumberFormatException e) { } } mat = new MagicUnknownMaterial(type, data); if (params.length >= 3) { try { radius = Integer.parseInt(params[2]); } catch (NumberFormatException e) { } } if (params.length >= 4) { try { tickInterval = Integer.parseInt(params[3]); } catch (NumberFormatException e) { } } } } @Override public void loadFromConfig(ConfigurationSection config) { mat = MagicSpells.getItemNameResolver().resolveBlock(config.getString("type", "fire")); radius = config.getInt("radius", radius); tickInterval = config.getInt("expand-interval", tickInterval); } @Override public void playEffectLocation(Location location) { if (mat == null) return; // get nearby players Item item = location.getWorld().dropItem(location, new ItemStack(Material.STONE, 0)); List<Entity> nearbyEntities = item.getNearbyEntities(20, 20, 20); item.remove(); List<Player> nearby = new ArrayList<Player>(); for (Entity e : nearbyEntities) { if (e instanceof Player) { nearby.add((Player)e); } } // start animation Block b = location.getBlock(); if (!BlockUtils.isPathable(b)) { b = b.getRelative(BlockFace.UP); } new NovaAnimation(nearby, location.getBlock(), mat, radius, tickInterval); } private class NovaAnimation extends SpellAnimation { List<Player> nearby; Block center; MagicMaterial mat; int radius; Set<Block> blocks; public NovaAnimation(List<Player> nearby, Block center, MagicMaterial mat, int radius, int tickInterval) { super(tickInterval, true); this.nearby = nearby; this.center = center; this.mat = mat; this.radius = radius; blocks = new HashSet<Block>(); } @Override protected void onTick(int tick) { // remove old fire blocks for (Block block : blocks) { for (Player p : nearby) { Util.restoreFakeBlockChange(p, block); } } blocks.clear(); if (tick <= radius) { // set next ring on fire int bx = center.getX(); int y = center.getY(); int bz = center.getZ(); for (int x = bx - tick; x <= bx + tick; x++) { for (int z = bz - tick; z <= bz + tick; z++) { if (Math.abs(x-bx) == tick || Math.abs(z-bz) == tick) { Block b = center.getWorld().getBlockAt(x,y,z); if (b.getType() == Material.AIR || b.getType() == Material.LONG_GRASS) { Block under = b.getRelative(BlockFace.DOWN); if (under.getType() == Material.AIR || under.getType() == Material.LONG_GRASS) { b = under; } for (Player p : nearby) { Util.sendFakeBlockChange(p, b, mat); } blocks.add(b); } else if (b.getRelative(BlockFace.UP).getType() == Material.AIR || b.getRelative(BlockFace.UP).getType() == Material.LONG_GRASS) { b = b.getRelative(BlockFace.UP); for (Player p : nearby) { Util.sendFakeBlockChange(p, b, mat); } blocks.add(b); } } } } } else if (tick > radius+1) { // stop if done stop(); } } } }