| package net.glowstone.entity; |
| |
| import com.flowpowered.network.Message; |
| import net.glowstone.EventFactory; |
| import net.glowstone.GlowWorld; |
| import net.glowstone.block.GlowBlock; |
| import net.glowstone.entity.physics.BoundingBox; |
| import net.glowstone.net.message.play.entity.SpawnLightningStrikeMessage; |
| import org.bukkit.Location; |
| import org.bukkit.Material; |
| import org.bukkit.Sound; |
| import org.bukkit.block.BlockFace; |
| import org.bukkit.block.BlockState; |
| import org.bukkit.entity.Damageable; |
| import org.bukkit.entity.Entity; |
| import org.bukkit.entity.EntityType; |
| import org.bukkit.entity.LightningStrike; |
| import org.bukkit.event.block.BlockIgniteEvent; |
| import org.bukkit.event.block.BlockIgniteEvent.IgniteCause; |
| import org.bukkit.event.entity.EntityDamageEvent.DamageCause; |
| import org.bukkit.util.Vector; |
| |
| import java.util.Arrays; |
| import java.util.List; |
| import java.util.Random; |
| |
| /** |
| * A GlowLightning strike is an entity produced during thunderstorms. |
| */ |
| public class GlowLightningStrike extends GlowWeather implements LightningStrike { |
| |
| /** |
| * How long this lightning strike has to remain in the world. |
| */ |
| private final int ticksToLive; |
| private final Random random; |
| /** |
| * Whether the lightning strike is just for effect. |
| */ |
| private boolean effect; |
| |
| public GlowLightningStrike(Location location, boolean effect, Random random) { |
| super(location); |
| this.effect = effect; |
| ticksToLive = 30; |
| this.random = random; |
| } |
| |
| @Override |
| public EntityType getType() { |
| return EntityType.LIGHTNING; |
| } |
| |
| @Override |
| public void setGlowing(boolean b) { |
| |
| } |
| |
| @Override |
| public boolean isGlowing() { |
| return false; |
| } |
| |
| @Override |
| public boolean isEffect() { |
| return effect; |
| } |
| |
| @Override |
| public void pulse() { |
| super.pulse(); |
| if (getTicksLived() >= ticksToLive) { |
| remove(); |
| } |
| if (getTicksLived() == 1) { |
| GlowWorld world = (GlowWorld) location.getWorld(); |
| // Play Sound |
| world.playSound(location, Sound.ENTITY_LIGHTNING_THUNDER, 10000, 0.8F + random.nextFloat() * 0.2F); |
| world.playSound(location, Sound.ENTITY_GENERIC_EXPLODE, 2, 0.5F + random.nextFloat() * 0.2F); |
| |
| if (!effect) { // if it's not just a visual effect |
| // set target block on fire if required |
| if (world.getGameRuleMap().getBoolean("doFireTick")) { |
| GlowBlock block = world.getBlockAt(location); |
| setBlockOnFire(block); |
| for (int i = 0; i < 4; i++) { |
| int x = location.getBlockX() - 1 + random.nextInt(3); |
| int z = location.getBlockZ() - 1 + random.nextInt(3); |
| int y = location.getBlockY() - 1 + random.nextInt(3); |
| block = world.getBlockAt(x, y, z); |
| setBlockOnFire(block); |
| } |
| } |
| |
| // deal damage to nearby entities |
| for (Entity entity : getNearbyEntities(3, 6, 3)) { |
| if (entity instanceof Damageable) { |
| ((Damageable) entity).damage(5, this, DamageCause.LIGHTNING); |
| } |
| entity.setFireTicks(entity.getMaxFireTicks()); |
| } |
| } |
| } |
| } |
| |
| @Override |
| public List<Message> createSpawnMessage() { |
| double x = location.getX(); |
| double y = location.getY(); |
| double z = location.getZ(); |
| return Arrays.<Message>asList(new SpawnLightningStrikeMessage(id, x, y, z)); |
| } |
| |
| @Override |
| public List<Message> createUpdateMessage() { |
| return Arrays.asList(); |
| } |
| |
| @Override |
| public List<Entity> getNearbyEntities(double x, double y, double z) { |
| // This behavior is similar to CraftBukkit, where a call with args |
| // (0, 0, 0) finds any entities whose bounding boxes intersect that of |
| // this entity. |
| |
| BoundingBox searchBox = BoundingBox.fromPositionAndSize(location.toVector(), new Vector(0, 0, 0)); |
| Vector vec = new Vector(x, y, z); |
| Vector vec2 = new Vector(0, 0.5 * y, 0); |
| searchBox.minCorner.subtract(vec).add(vec2); |
| searchBox.maxCorner.add(vec).add(vec2); |
| |
| return world.getEntityManager().getEntitiesInside(searchBox, this); |
| } |
| |
| private void setBlockOnFire(GlowBlock block) { |
| if (block.isEmpty() && block.getRelative(BlockFace.DOWN).isFlammable()) { |
| BlockIgniteEvent igniteEvent = new BlockIgniteEvent(block, IgniteCause.LIGHTNING, this); |
| EventFactory.callEvent(igniteEvent); |
| if (!igniteEvent.isCancelled()) { |
| BlockState state = block.getState(); |
| state.setType(Material.FIRE); |
| state.update(true); |
| } |
| } |
| } |
| |
| public LightningStrike.Spigot spigot() { |
| return null; |
| } |
| } |