[1.9] Hologram adding/removing with AsyncPlayerChatEvent!

Discussion in 'Spigot Plugin Development' started by tokyojack, May 12, 2016.

  1. Hello all!

    So, I'm trying to create a hologram with a simple word like "Why" and "And" and when the players says the word in chat, it is removed! This is what I have at the moment. Correction and/or improvements of my code are very much welcomed!

    Code (Text):

    //I've shortened this down to the main problem, so I might of missed something when pasting it in here!
    private HashMap < Integer, ArmorStand > IntArmour = new HashMap < Integer, ArmorStand > ();
    private HashMap < String, Integer > IntName = new HashMap < String, Integer > ();
    public ArrayList < String > TypingName = new ArrayList < String > ();
    public int armourstandnumber;

    public void createHolograms12(Location location, String name) {
        armourstandnumber++;
        ArmorStand GeneratedArmorStand = (ArmorStand) location.getWorld().spawnEntity(location, EntityType.ARMOR_STAND);
        GeneratedArmorStand.setArms(false);
        GeneratedArmorStand.setGravity(false);
        GeneratedArmorStand.setVisible(false);
        GeneratedArmorStand.setCustomName(ChatColor.translateAlternateColorCodes('&', name));
        GeneratedArmorStand.setCustomNameVisible(true);
        IntName.put(name, armourstandnumber);
        IntArmour.put(armourstandnumber, GeneratedArmorStand);
        return;
    }

    public void CreateHologram(Player player) {

        // MyAPI is a API I created for myself, if people are wondering
        int randomNumber = MyAPI.RandomNumber(5);
        SpotA = new Location(Bukkit.getWorld("world"), -8, 101, 15);

        if (randomNumber == 3)) {
        createHolograms12(SpotA, "&2Bot");
        TypingName.add("Bot");
        return;
    }
    }


    @EventHandler
    public void messageSent(AsyncPlayerChatEvent event) {
        if (event.isCancelled()) {
            return;
        }

        Player player = event.getPlayer();
        String msg = event.getMessage();

        if (TypingName.toString().toLowerCase().contains(msg) || TypingName.toString().toUpperCase().contains(msg) ||
            TypingName.toString().contains(msg)) {


            //This is the main part where im stumped,
            // I'm thinking some sort of message checker to see if it has a word in TypingName
            //And if so, remove it.
            IntArmour.remove(IntName.get(msg));
            TypingName.remove(msg);
        }
    }
    I'm pretty sure there's a MUCH easier way on doing this, but at the time, I cant think of anything else.

    Hopes everyone has a great day/night,
    Jack!
     
  2. Depending on the usage of your code, is it really necessary to create a new Hologram each time?

    #1 You should build on the interface instead of the implementation of HashMaps and ArrayLists.
    Code (Java):
    private Map<Integer, ArmorStand> intAmour = new HashMap();
    public List<String> typingName = new ArrayList();
    #2 Following coding conventions. Labels should be lowerCaseCamel.
    #3 Make your Maps and List final.
    #4 Is it really necessary to store the Integer with the ArmorStand or the ArmorStand with the id?
    #5 That return at the end of your method is useless.

    Also, if you're using the AsyncPlayerChatEvent, there are times where the event will be asynchronous. If that code is called on an asynchronous thread an error will be thrown. Make sure to jump back on the main server thread with a BukkitRunnable.
     
    #2 Warren1001, May 12, 2016
    Last edited: May 12, 2016
  3. MiniDigger

    Supporter

    lowerCamelCase ^^
    I would sugesst calling toLowerCase on both strings (msg and typingname). your current checks for 3 times the workload and still don't catch everything, eg:
    TeSt and Test will not be detected by the if. it will try test vs Test, TEST vs Test and TeSt vs Test and every check will fail. If you do lowercase on both once it will do test vs test and it will match.
     
  4. Oh rip. I didn't see there was more code.
     
  5. Can you explain your paragraph about AsyncPlayerChatEvent? Im not sure what you are talking about. :confused:

    This is very much correct, I almost forgot about it!

    Code (Text):
        // I've shortened this down to the main problem, so I might of missed
        // something when pasting it in here!
        public final Map < Integer, ArmorStand > IntAmour = new HashMap < > ();
        public final List < String > TypingName = new ArrayList < > ();
        public int armourstandnumber;

        public ArmorStand CreateHolograms(Location location, String name) {
            ArmorStand GeneratedArmorStand = (ArmorStand) location.getWorld().spawnEntity(location, EntityType.ARMOR_STAND);
            GeneratedArmorStand.setArms(false);
            GeneratedArmorStand.setGravity(false);
            GeneratedArmorStand.setVisible(false);
            GeneratedArmorStand.setCustomName(ChatColor.translateAlternateColorCodes('&', name));
            GeneratedArmorStand.setCustomNameVisible(true);
            return GeneratedArmorStand;
        }
        public void CreateHologramPlace(Player player) {
            armourstandnumber++;
            // MyAPI is a API I created for myself, if people are wondering
            int randomNumber = MyAPI.RandomNumber(5);
            Location SpotA = new Location(Bukkit.getWorld("world"), -8, 101, 15);

            if (randomNumber == 3) {
                IntAmour.put(armourstandnumber, CreateHolograms(SpotA, "But"));
                TypingName.add("But");
            }
        }

        @EventHandler
        public void MessageSent(AsyncPlayerChatEvent event) {
            if (event.isCancelled()) {
                return;
            }

            String msg = event.getMessage();

            if (TypingName.toString().toLowerCase().contains(msg.toLowerCase()) ||
                TypingName.toString().toUpperCase().contains(msg.toUpperCase()) ||
                TypingName.toString().contains(msg)) {

                //This is the main part where I'm stumped,
                // I'm thinking some sort of message checker to see if it has a word in TypingName
                //And if so, remove it.

                //It would go though the typingName and see if it has it, and if so, create a string of it
                //then remove it from "TypingName"
                //I think its something to do with a For statement, but I can't rack my head for the proper coding.
               // I haven't tested this code, so do keep that in mind!


            }
        }
    Yes, both of you are very much correct. I forgot to mention, but I made this at around 2AM and posted it. So I never really checked it over and its hard to code with a sleepy head :confused:. I was planning to post it and sleep on it, and If I didn't think of anything, I was gonna to continue.
     
  6. MiniDigger

    Supporter

    coffee my friend, coffe solves such problems ^^
    much coffee