Per-block Holograms, Consistent shooting, etc

Discussion in 'Plugin Development' started by plisov, Nov 12, 2017.

Thread Status:
Not open for further replies.
  1. Offline

    plisov

    I'm trying to create an automatic cannon plugin and I have the majority of it completed however there are a few bugs with it. For example, when I place a cannon down, it creates a hologram which is fine however when I place the second cannon down and break both of the cannons, only one hologram is removed. The other one stays. I need to find a way to make a per-block hologram system. Also, since I'm using Scheduled Runnables, each time I place a cannon down, it begins to shoot faster and faster as it's not ending the old runnable. I would need to either find a way to make it shoot without a runnable to cancel the runnable when the block is broken. Finally, I need to save the locations of the cannons because every time I reload the plugin or server, the cannons become inactive until I replace the cannon.

    • Per-block holograms
    • Cancel runnables on block break
    • Keep cannons active even after server reload/restart
    Code:
    package me.plisov.cannons;
    
    import java.util.HashMap;
    import java.util.List;
    
    import org.bukkit.Bukkit;
    import org.bukkit.ChatColor;
    import org.bukkit.Location;
    import org.bukkit.Material;
    import org.bukkit.Particle;
    import org.bukkit.block.Block;
    import org.bukkit.entity.Entity;
    import org.bukkit.entity.EntityType;
    import org.bukkit.entity.Fireball;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.EventPriority;
    import org.bukkit.event.Listener;
    import org.bukkit.event.block.BlockBreakEvent;
    import org.bukkit.event.block.BlockPlaceEvent;
    import org.bukkit.event.entity.EntityDamageByEntityEvent;
    import org.bukkit.event.entity.EntityExplodeEvent;
    import org.bukkit.event.entity.ProjectileHitEvent;
    import org.bukkit.util.Vector;
    
    import com.gmail.filoghost.holograms.api.HolographicDisplaysAPI;
    import com.gmail.filoghost.holographicdisplays.api.Hologram;
    import com.gmail.filoghost.holographicdisplays.api.HologramsAPI;
    
    /**
    *
    * Custom cannons that shoot at players
    *
    * @author plisov
    *
    */
    
    @SuppressWarnings("deprecation")
    public class BlockPlace implements Listener {
    
        HashMap<Location, Long> cooldowns = new HashMap<Location, Long>();
    
        Hologram hologram = null;
    
        int radius = 10;
    
        @EventHandler
        public void onBlockPlace(BlockPlaceEvent event) {
    
            Location topBlockLoc = new Location(event.getBlock().getWorld(), event.getBlock().getX(),
                    event.getBlock().getLocation().getY() + 1, event.getBlock().getZ());
    
            Location buttomBlockLoc = new Location(event.getBlock().getWorld(), event.getBlock().getX(),
                    event.getBlock().getLocation().getY() - 1, event.getBlock().getZ());
    
            Location currentBlockLoc = event.getBlock().getLocation().add(0, 2, 0);
    
            Block topBlock = topBlockLoc.getBlock();
            Block currentBlock = event.getBlock();
            Block bottomBlock = buttomBlockLoc.getBlock();
    
            if (currentBlock.getType().equals(Material.OBSIDIAN)) {
    
                if (bottomBlock.getType().equals(Material.BEDROCK)) {
    
                    Location hologramLoc = currentBlockLoc.add(0.5, 0, 0.5);
                   
                    hologram = HologramsAPI.createHologram(Bukkit.getPluginManager().getPlugin("PrimitiveCannons"),
                            hologramLoc);
                    hologram.appendTextLine(ChatColor.YELLOW + "Cannon");
                    hologram.appendTextLine(ChatColor.BLUE + "T1");
                }
            }
    
            Bukkit.getScheduler().scheduleSyncRepeatingTask(Bukkit.getPluginManager().getPlugin("PrimitiveCannons"),
                    new Runnable() {
                        public void run() {
    
                            if (currentBlock.getType().equals(Material.OBSIDIAN)) {
    
                                if (bottomBlock.getType().equals(Material.BEDROCK)) {
    
                                    double radiusSquared = radius * radius;
    
                                    List<Entity> entites = (List<Entity>) currentBlock.getWorld()
                                            .getNearbyEntities(currentBlockLoc, radius, radius, radius);
    
                                    for (Entity entity : entites) {
    
                                        Location particleLoc = new Location(currentBlockLoc.getWorld(),
                                                currentBlockLoc.getX(), entity.getLocation().getY(),
                                                currentBlockLoc.getZ());
    
                                        if (entity.getLocation().distanceSquared(particleLoc) > radiusSquared)
                                            continue;
    
                                        if (entity instanceof Player) {
    
                                            Vector vector = entity.getLocation().toVector()
                                                    .subtract(topBlockLoc.toVector());
    
                                            Fireball fb = (Fireball) currentBlock.getWorld().spawnEntity(currentBlockLoc,
                                                    EntityType.FIREBALL);
    
                                            fb.getWorld().spawnParticle(Particle.ENCHANTMENT_TABLE, fb.getLocation(), 20);
                                            // velocity is bugged ... cannot change the speed
                                            // fb.setVelocity(new Vector(0, -0.8, 0));
                                            fb.setDirection(vector);
                                            fb.setIsIncendiary(false);
    
                                            sphere(particleLoc, 360, radius, Particle.FLAME);
                                            hollowCircle(particleLoc, 360, radius, Particle.VILLAGER_HAPPY);
    
                                            // event.getPlayer().sendMessage("10");
    
                                            event.getPlayer().sendMessage("Launched");
                                            return;
                                        }
                                    }
                                }
                            }
                        }
                    }, 0, 30);
        }
    
        @EventHandler
        public void onBlockBreak(BlockBreakEvent event) {
    
            Location topBlockLoc = new Location(event.getBlock().getWorld(), event.getBlock().getX(),
                    event.getBlock().getLocation().getY() + 1, event.getBlock().getZ());
    
            Location buttomBlockLoc = new Location(event.getBlock().getWorld(), event.getBlock().getX(),
                    event.getBlock().getLocation().getY() - 1, event.getBlock().getZ());
    
            Location currentBlockLoc = event.getBlock().getLocation();
    
            Block topBlock = topBlockLoc.getBlock();
            Block currentBlock = event.getBlock();
            Block bottomBlock = buttomBlockLoc.getBlock();
    
            // event.getPlayer().sendMessage("1");
            if (currentBlock.getType().equals(Material.OBSIDIAN)) {
    
                // event.getPlayer().sendMessage("2");
    
                if (bottomBlock.getType().equals(Material.BEDROCK)) {
    
                    hologram.delete();
    
                }
            }
    
        }
    
        @EventHandler(priority = EventPriority.HIGH)
        public void onEntityExplode(EntityExplodeEvent event) {
            if (event.getEntity() instanceof Fireball) {
                event.setCancelled(true);
            }
        }
       
        @EventHandler
        public void onFireballHit(EntityDamageByEntityEvent event) {
            if (event.getDamager() instanceof Fireball) {
                event.setDamage(15D);
            }
        }
    
        public static void hollowCircle(Location loc, int spikeAmount, float radius, Particle particle) {
    
            // loc.add(0, 5, 0);
    
            loc = loc.subtract(0, 0, 0);
    
            // If you make radius >= 0 it will spawn an entity in the middle where the
            // entity is standing. If you make it radius > 0 the entity will not spawn in
            // the middle of the circle where the entity is standing.
            // Adding .subtract(0, 5, 0) will make the cirlces go down 5 times every time
            // until radius is not greater than 0
            // loc = loc.subtract(0, 5, 0);
            for (int i = 0; i < spikeAmount; i++) {
                double angle, x, z;
                angle = 2 * Math.PI * i / spikeAmount;
                x = Math.cos(angle) * radius;
                z = Math.sin(angle) * radius;
                loc.add(x, 0, z);
    
                loc.getWorld().spawnParticle(particle, loc, 5);
                // player.getWorld().spawnEntity(loc.add(0, 0, 0), entity).setFireTicks(10); //
                // Change the y in add(0, 0, // 0)
                // to add a helix effect
    
                loc.subtract(x, 0, z);
            }
        }
    
        private void sphere(Location loc, int spikeAmount, float radius, Particle particle) {
            for (double phi = 0; phi <= Math.PI; phi += Math.PI / 15) {
                for (double theta = 0; theta <= 2 * Math.PI; theta += Math.PI / 30) {
                    double r = radius;
                    double x = r * Math.cos(theta) * Math.sin(phi);
                    double y = r * Math.cos(phi) + 2;
                    double z = r * Math.sin(theta) * Math.sin(phi);
    
                    loc.add(x, y, z);
                    loc.getWorld().spawnParticle(particle, loc, 1, 0F, 0F, 0F, 0.001);
                    loc.subtract(x, y, z);
                }
            }
    
        }
    
        public Hologram createHologram(Location currentBlockLoc) {
    
            Hologram hologram = (Hologram) HolographicDisplaysAPI.createHologram(
                    Bukkit.getPluginManager().getPlugin("PrimitiveCannons"), currentBlockLoc.add(0, 2, 0),
                    ChatColor.GRAY + "Building: " + ChatColor.GREEN + "HOUSE" + ChatColor.RED + " 59%");
    
            return hologram;
        }
    }
    
    Any help is much appreciated,
    plisov
     
  2. Offline

    Zombie_Striker

    @plisov
    1. I don't see anything in your code that deletes existing holograms if on breaking. If you have it, can you refer to which line/method you do that?
    2. Best way to do this would be to create a new class to store all the information for all the cannons. Then, every time you want to create a new cannon, create a new instance of that class and store it somewhere. Then, when you destroy it, call some destroy method that handles the removal and clearing of all the variables relating to the cannon.
    3. Adding onto #2, let the class implement ConfigurationSerializable. From there, just save the instances of the cannons to the config, and load them in the onEnable
     
  3. Offline

    plisov

    Sorry for the late response. Here is how I remove the holograms
    Code:
        @EventHandler
        public void onBlockBreak(BlockBreakEvent event) {
    
            Location topBlockLoc = new Location(event.getBlock().getWorld(), event.getBlock().getX(),
                    event.getBlock().getLocation().getY() + 1, event.getBlock().getZ());
    
            Location buttomBlockLoc = new Location(event.getBlock().getWorld(), event.getBlock().getX(),
                    event.getBlock().getLocation().getY() - 1, event.getBlock().getZ());
    
            Location currentBlockLoc = event.getBlock().getLocation();
    
            Block topBlock = topBlockLoc.getBlock();
            Block currentBlock = event.getBlock();
            Block bottomBlock = buttomBlockLoc.getBlock();
    
            // event.getPlayer().sendMessage("1");
            if (currentBlock.getType().equals(Material.OBSIDIAN)) {
    
                // event.getPlayer().sendMessage("2");
    
                if (bottomBlock.getType().equals(Material.BEDROCK)) {
    
                    hologram.delete();
    
                }
            }
    
        }
    
    I'm not too familiar with ConfigurationSerializable. What is it? How do I use it?
     
  4. Offline

    Zombie_Striker

    @plisov
    Its basically an easy way to convert a class into a Map of values, which can be saved to a config. Basically, you need two things; a serialize method and a new constructor:
    Code:
    //Lets assume you have these two values
    int id = 1;
    String somevalue = "somevalue";
    
    @Override
        public Map<String, Object> serialize() {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("id", this.id);
            map.put("somevalue", this.somevalue);
            return m;
        }
    Now the values "id" and "somevalue" are stored into the class. Then, for the constructor, we would have:
    Code:
    public void YOUR_CLASS(Map<String,Object> map){
    //This now takes the values from the config (the map) and sets the fields, so it basically the same object.
      this.id = (int) map.get("id");
      this.somevalue = (String)map.get("somevalue");
    }
     
Thread Status:
Not open for further replies.

Share This Page