Solved Who attacks the most damage to BOSS, get this player's name

Discussion in 'Spigot Plugin Development' started by iO_5, Jul 29, 2018.

  1. You can not write code.
    Can give me ideas.
    Because I use the HasMap method is cumbersome.
    Thanks.

    public static Map<String, Double> killNumber = new HashMap<String, Double>();
    public static Map<String, String> playerList = new HashMap<String, String>();
    public static Map<String, List<Integer>> entityList = new HashMap<String, List<Integer>>();
     
    #1 iO_5, Jul 29, 2018
    Last edited: Jul 30, 2018
  2. Store the amount of damage each player does, then sort it, then get the first index.
     
    • Agree Agree x 3
  3. Yes, or use treemap, or just make variable with object where you hold player's uuid and damage, loop all keys and values, if current value is bigger than in variable, set variable to value, and still keep looping.. But it's optional solutions, i prefer the first with sorting.
     
  4. What kind of storage?
    EntityDamageByEntityEvent
    Save Entity Name
    Player attack Entity > save Entity's name in HasMap(What?<-I don't know)
    Save Damage Number
    I don't konw...->xxx HasMap
    EntityDeathEvent
    getNearbyEntities
    getPlayer HasMap Max Damage
    Sorry, My English is not good, I hope you can understand it.
    I used the Google translation, and I tried to express my ideas.
     
  5. My mind is hindered
    About here

    EntityDamageByEntityEvent
    Save Entity Name
    Player attack Entity > save Entity's name in HasMap(What?<-I don't know)
    Save Damage Number
    I don't konw...->xxx HasMap
    EntityDeathEvent
    getNearbyEntities
    getPlayer HasMap Max Damage
    Sorry, My English is not good, I hope you can understand it.
    I used the Google translation, and I tried to express my ideas.
     
  6. How about a list of objects that hold a player's UUID and damage? You can then sort the list with list.sort.
     
  7. I suggest that you use a Map which will store an Entity as a key and another Map as a value which will store a player instance (or an UUID) and a double for the damage.

    Our key (Entity) will be used to retrieve from which entity we will be taking the top damage dealer.

    After we've got that, we will be retrieving the damage from X player.

    You can then use java 8 to get the top damage dealer from the map retrieved by the first map.

    EDIT: If you know that there will be no chances of a player attacking something else which may add more "false" damage since the player is not attacking the boss then you can skip the first map and go right to the Map which will be holding a player instance (or UUID) and double (damage)


    It would look something like this:

    Code (Java):

    EntityDamageByEntityEvent {

    if (the entity is not a boss) stop the code

    if (if the boss is not in the hashmap) {
    put the boss in the hashmap + put the player in the hashmap of the boss hashmap
    stop the code here
    }

    put the new damage to the entity (boss) map by putting the previous damage and the new damage.

    }
     
    Code (Java):

    EntityDeathEvent{
    if (entity is boss) {
    get the entity (boss) map and by using java 8 get the top damage dealer (top double)
    and now do whatever you wish.
      }
    }
     
     
    #7 darklazerog, Jul 29, 2018
    Last edited: Jul 29, 2018
    • Agree Agree x 2
  8. I agree with this approach, just an array list of objects and then sort the array by damage.
     
  9. OK, thank you, I will try it later.
     
  10. This should suffice:
    My method is really simple, and the sorting is all done by Gueva (google commons).

    Code (Java):
    /**
    * Project created by ExpDev
    */

    public class DamageListener implements Listener {

        // Map where to store damage
        private Map<Player, Double> map = new HashMap<>();

        /**
         * Constructs a damage listener, will register listener with Bukkit
         *
         * @param plugin Plugin
         */

        public void DamageListener(Plugin plugin) {
            Bukkit.getPluginManager().registerEvents(this, plugin);
        }

        /**
         * Gets an immutable sorted copy of the damage map
         *
         * @return Immutable, sorted copy of damage map
         */

        public SortedMap<Player, Double> getImmutableSorted() {
            return ImmutableSortedMap.copyOf(map, Ordering.natural().onResultOf(Functions.forMap(map)));
        }

        /**
         * Listener method for when damage is done to an entity by a player
         *
         * @param event Event
         */

        @EventHandler(priority = EventPriority.NORMAL)
        public void onDamage(EntityDamageByEntityEvent event) {
            // Ensure that damager is a player
            Entity damager = event.getDamager();
            if (damager instanceof  Player) {
                // Update damage done, !!! you have to make sure damaged entity is "the boss" !!!
                Player player = (Player) damager;
                map.put(player, this.getDamageFor(player) + event.getDamage());
            }
        }

        /**
         * Gets the total amount of damage a player has done
         *
         * @param player Player that has done damage
         * @return Damage player has done
         */

        public double getDamageFor(Player player) {
            if (!map.containsKey(player)) return 0d;
            return map.get(player);
        }

        /**
         * Gets the player that did the most damage
         *
         * @return Player that did most damage
         */

        public Player getTopDamager() {
            // Player that did the most damage should be at the top (first key)
            return this.getImmutableSorted().firstKey();
        }
     
    }
     
    • Like Like x 2
  11. Thank you, I will try it later.;)

    how save boss map, not map?
    I have never seen and learned this: "Ordering.natural().onResultOf", I don't understand this.
     
    #11 iO_5, Jul 30, 2018
    Last edited: Jul 30, 2018
  12. The onResultOf just makes guava sort the map by value instead of key. And the reason you haven’t seen it before is because it’s not native java, but a library called google commons (Guava), but it’s included with spigot so you have access to it.

    And I don’t know how you determine something is a Boss. Maybe you have a Boss class or something?
     
    • Agree Agree x 1
  13. I just tested the code and found that getTopDamager() is not the most damage
     
  14. Oh, I seem to know,
    but I have an uncertain question: map save who boss?
    Map save all getDamage?
    How to delete the damage map after BOSS death?

    But getTopDamager() not get MaxDamge player Oh, firstKey

    Code (Text):

        private Map<Player, Double> map = new HashMap<>();
     
        @EventHandler
        void entityDeath(EntityDeathEvent e) {
            if ( !(e.getEntity() instanceof Player) ) {
                List<ItemStack> drops = e.getDrops();
                for (ItemStack item : drops) {
                    getTopDamager().getInventory().addItem(item);
                }
                e.getDrops().clear();
                for ( Player p : Bukkit.getOnlinePlayers() ) {
                    map.remove(p);
                }
            }
        }
     
        public SortedMap<Player, Double> getImmutableSorted() {
            return ImmutableSortedMap.copyOf(map, Ordering.natural().onResultOf(Functions.forMap(map)));
        }
     
        @EventHandler(priority = EventPriority.NORMAL)
        public void onDamage(EntityDamageByEntityEvent event) {
            Entity damager = event.getDamager();
            if (damager instanceof  Player) {
                Player player = (Player) damager;
                map.put(player, getDamageFor(player) + event.getDamage());
            }
        }
     
        public double getDamageFor(Player player) {
            if (!map.containsKey(player)) return 0d;
            return map.get(player);
        }
     
        public Player getTopDamager() {
            return getImmutableSorted().firstKey();
        }
     
     
    #14 iO_5, Jul 30, 2018
    Last edited: Jul 30, 2018
  15. Try replacing Ordering.natural() with Ordering.natural().reverse(), that should make the top damager be the first key instas if the last (which is what I believe natural does; 1-10 instead of 10-1).

    It was late and for some reason I thought it was gonna go too down instead of down top. But reverse reverse fix that.
     
    #15 ExpDev, Jul 30, 2018
    Last edited: Jul 30, 2018
  16. like this?
    Code (Text):

    public SortedMap<Player, Double> getImmutableSorted() {
            return ImmutableSortedMap.copyOf(map, Ordering.reverse().onResultOf(Functions.forMap(map)));
    }
     
    Cannot make a static reference to the non-static method reverse() from the type Ordering
     
  17. To begin with, to clear the map, just use Map#clear().

    And the first key is not top damager because the map is not reversed. Use instead "reversed":
    Code (Java):
    /**
    * Gets an immutable sorted copy of the damage map
    *
    * @return Immutable, sorted copy of damage map
    */

    public SortedMap<Player, Double> getImmutableSorted() {
        return ImmutableSortedMap.copyOf(map, Ordering.natural().reverse().onResultOf(Functions.forMap(map)));
    }
    EDIT: Full code
    Code (Java):
    /**
    * Project created by ExpDev
    */

    public class DamageListener implements Listener {

        // Map where to store damage
        private Map<Player, Double> map = new HashMap<>();

        /**
         * Constructs a damage listener, will register listener with Bukkit
         *
         * @param plugin Plugin
         */

        public void DamageListener(Plugin plugin) {
            Bukkit.getPluginManager().registerEvents(this, plugin);
        }

        /**
         * Gets an immutable sorted copy of the damage map
         *
         * @return Immutable, sorted copy of damage map
         */

        public SortedMap<Player, Double> getImmutableSorted() {
            return ImmutableSortedMap.copyOf(map, Ordering.natural().reverse().onResultOf(Functions.forMap(map)));
        }

        /**
         * Listener method for when damage is done to an entity by a player
         *
         * @param event Event
         */

        @EventHandler(priority = EventPriority.NORMAL)
        public void onDamage(EntityDamageByEntityEvent event) {
            // Ensure that damager is a player
            Entity damager = event.getDamager();
            if (damager instanceof  Player) {
                // Update damage done
                Player player = (Player) damager;
                map.put(player, this.getDamageFor(player) + event.getDamage());
            }
        }

        /**
         * Listener for when the boss is killed
         *
         * @param event Event
         */

        public void onKilled(EntityDeathEvent event) {
            Entity entity = event.getEntity();

            // if entity is boss, clear the map
            map.clear();
        }

        /**
         * Gets the total amount of damage a player has done
         *
         * @param player Player that has done damage
         * @return Damage player has done
         */

        public double getDamageFor(Player player) {
            if (!map.containsKey(player)) return 0d;
            return map.get(player);
        }

        /**
         * Gets the player that did the most damage
         *
         * @return Player that did most damage
         */

        public Player getTopDamager() {
            // Player that did the most damage should be at the top (first key)
            return this.getImmutableSorted().firstKey();
        }

    }
     
    • Agree Agree x 1
  18. Thanks. I have solved it.
    It's my code, What do you think of this code?
    Code (Text):

        public Player test(Map<Player,Integer> mapmap){
            List<Entry<Player,Integer>> list = new ArrayList<Entry<Player,Integer>>(mapmap.entrySet());
            Collections.sort(list, new Comparator<Map.Entry<Player,Integer>>() {
            public int compare(Map.Entry<Player,Integer> o1,Map.Entry<Player,Integer> o2) {
                    //return (o1.getValue() - o2.getValue());
                return ( o2.getValue() - o1.getValue() );
              }
            });
            return list.get(0).getKey();
        }
     
     
  19. awesome! Thank you for your patience.
    Your code can be used.