Elements not being added to ArrayList

Discussion in 'Spigot Plugin Development' started by Greenadine, Jun 29, 2018.

  1. I'm trying to create a system for signs that when a sign is interacted with, it will teleport a player to either the spawn of a world, or the hub. For that to work, I created a listener that will handle creating such a sign.

    Creating a 'spawn' type sign is working just fine. However, when trying to create any of the other types, everything works just fine and you get the confirmation message that it has been created, but for some unknown reason to me, the new WSSign element is not being added to the ArrayList. I've tried several methods of fixing this problem, such as changing the way the signs are being stored, changing the way they are being added, but without result.

    So in short, a 'spawn' type sign is being added to the ArrayList, but all the other types are not for some reason. And I've run out of ideas as for why it is like this.

    This is the mehod of the listener that handles creating signs (don't mind the unnecessary logging, it was for debugging):

    Code (Java):
    @EventHandler
        public void onSignCreate(SignChangeEvent e) {
            main.log.info("SignChangeEvent");
            if(!(e.getLine(0).equals("[worldspawns]") || e.getLine(0).equals("[ws]"))) {
                return;
            }
         
            main.log.info("Header detected");
         
            Player p = e.getPlayer();
         
            if(e.getLine(1).equals("spawn")) {
                if(!p.hasPermission(new Permissions().sign_spawn)) {
                    p.sendMessage(noperm.replaceAll("%type%", "spawn"));
                    return;
                }
             
                World w = main.getServer().getWorld(e.getLine(2));
             
                if(w == null) {
                    e.setLine(0, color(main.getConfig().getString("sign.line1")));
                    e.setLine(1, color(main.getConfig().getString("sign.spawn.line2")));
                    e.setLine(2, color("&cInvalid world!"));
                    e.setLine(3, color(""));
                    return;
                }
             
                e.setLine(0, color(main.getConfig().getString("sign.line1")));
                e.setLine(1, color(main.getConfig().getString("sign.spawn.line2")));
                e.setLine(2, color(main.getConfig().getString("sign.spawn.line3").replaceAll("%world%", w.getName())));
                e.setLine(3, color(main.getConfig().getString("sign.spawn.line4")));
             
                WSSign sign = new WSSign((Sign) e.getBlock().getState(), SignType.SPAWN);
                sign.setSpawnWorld(w);
                main.getSigns().add(sign);
             
                p.sendMessage(prefix + color(Lang.SIGN_CREATE.toString().replaceAll("%type%", "spawn")));
                return;
            }
         
            if(e.getLine(1).equals("fspawn")) {
                if(!p.hasPermission(new Permissions().sign_fspawn)) {
                    p.sendMessage(noperm.replaceAll("%type%", "fspawn"));
                    return;
                }
             
                World w = main.getServer().getWorld(e.getLine(2));
             
                if(w == null) {
                    e.setLine(0, color(main.getConfig().getString("sign.line1")));
                    e.setLine(1, color(main.getConfig().getString("sign.fspawn.line2")));
                    e.setLine(2, color("&cInvalid world!"));
                    e.setLine(3, "");
                    return;
                }
             
                e.setLine(0, color(main.getConfig().getString("sign.line1")));
                e.setLine(1, color(main.getConfig().getString("sign.fspawn.line2")));
                e.setLine(2, color(main.getConfig().getString("sign.fspawn.line3").replaceAll("%world%", w.getName())));
                e.setLine(3, color(main.getConfig().getString("sign.fspawn.line4")));
             
                WSSign sign = new WSSign((Sign) e.getBlock().getState(), SignType.FSPAWN);
                sign.setSpawnWorld(w);
                main.getSigns().add(sign);
             
                p.sendMessage(prefix + color(Lang.SIGN_CREATE.toString().replaceAll("%type%", "fspawn")));
                return;
            }
         
            if(e.getLine(1).equals("hub")) {
                if(!p.hasPermission(new Permissions().sign_hub)) {
                    p.sendMessage(noperm.replaceAll("%type%", "hub"));
                    return;
                }
             
                e.setLine(0, color(main.getConfig().getString("sign.line1")));
                e.setLine(1, color(main.getConfig().getString("sign.hub.line2")));
                e.setLine(2, color(main.getConfig().getString("sign.hub.line3")));
                e.setLine(2, color(main.getConfig().getString("sign.hub.line4")));
             
                WSSign sign = new WSSign((Sign) e.getBlock().getState(), SignType.HUB);
                sign.setSpawnWorld(null);
                main.getSigns().add(sign);
             
                p.sendMessage(prefix + color(Lang.SIGN_CREATE.toString().replaceAll("%type%", "hub")));
                return;
            }
         
            if(e.getLine(1).equals("fhub")) {
                if(!p.hasPermission(new Permissions().sign_fhub)) {
                    p.sendMessage(noperm.replaceAll("%type%", "fhub"));
                    return;
                }
             
                e.setLine(0, color(main.getConfig().getString("sign.line1")));
                e.setLine(1, color(main.getConfig().getString("sign.fhub.line2")));
                e.setLine(2, color(main.getConfig().getString("sign.hub.line3")));
                e.setLine(2, color(main.getConfig().getString("sign.hub.line4")));
             
                WSSign sign = new WSSign((Sign) e.getBlock().getState(), SignType.FHUB);
                sign.setSpawnWorld(null);
                main.getSigns().add(sign);
             
                p.sendMessage(prefix + color(Lang.SIGN_CREATE.toString().replaceAll("%type%", "fhub")));
                return;
            }
         
            else {
                e.setLine(0, color(main.getConfig().getString("sign.line1")));
                e.setLine(1, color("&cInvalid sign type"));
                e.setLine(2, "");
                e.setLine(3, "");
                return;
            }
        }
    The ArrayList in Main.java is defined as follows:

    Code (Java):
    private ArrayList<WSSign> signs;
    And it is accessed by this method in Main.java:

    Code (Java):
    public ArrayList<WSSign> getSigns() {
            return signs;
        }
     
  2. Benz56

    Moderator Supporter

    • Agree Agree x 1
    • Informative Informative x 1
  3. ciz

    ciz

    The way I always use to do it is by making a method to get the list and also one to set it.

    In the class I'm trying to add to it I would make a local list like this:

    Code (Java):
    private ArrayList<String> localList = main.getList();
    Then I would add to the local one. When I finished adding i would update it.

    Code (Java):
    main.updateList(localList);
    I hope this helps a little bit.
     
    #3 ciz, Jun 29, 2018
    Last edited: Jun 29, 2018
  4. Hmm. From what I see, it honestly should work. Is there any stacktrace? If so please include. Also give a better description as to what is happening in your plugin.
     
  5. Oh sorry, forgot to post how it was initialized. The list is initialized in the onEnable() method. I have it like this because I have made a Saver class to first run through all saved signs, add them all to a new ArrayList, and then set them as the ArrayList in the Main class, like this:
    Code (Text):
    signs = saver.loadSigns();
    I've tried using List instead of ArrayList, but the outcome was the same.

    And thanks for that article. It's surprisingly helpful.

    That's the annoying part of all this: it does not give any stacktraces. I've been adding log messages to the code to find where the flaws are in the code, or if it maybe doesn't even get to a certain part of it, but that would not seem to be the case. The only parts of the code that are not working as intented, are these parts:
    Code (Java):
    main.getSigns().add(sign);
    As for a better description as to what is happening in my plugin:

    The base line is that a special sign can be created (handled by this listener stated in my original post). All that this listener should do, is in the end add a new valid WSSign to the List. Then the other classes that handle either destroying or interacting with such a sign will use the List to identify if such a sign is actually involved in an event.

    For example, here is one of those other classes, 'WSSignUse', which handles interacting with the signs:
    Code (Text):
    @EventHandler
        public void onSignUse(PlayerInteractEvent e) {
            if (!(e.getClickedBlock().getType() == Material.SIGN || e.getClickedBlock().getType() == Material.SIGN_POST
                    || e.getClickedBlock().getType() == Material.WALL_SIGN)) {
                return;
            }

            if (e.getAction() != Action.RIGHT_CLICK_BLOCK) {
                return;
            }

            Sign s = (Sign) e.getClickedBlock().getState();
            World sw = s.getWorld();
            int sx = s.getX();
            int sy = s.getY();
            int sz = s.getZ();

            WSSign sign = null;

            for (Iterator<WSSign> i = main.getSigns().iterator(); i.hasNext();) {
                WSSign ws = i.next();
                World wsw = ws.getWorld();
                int wsx = ws.getX();
                int wsy = ws.getY();
                int wsz = ws.getZ();

                if (wsw == sw && sx == wsx && sy == wsy && sz == wsz) {
                    sign = ws;
                    break;
                } else {
                    continue;
                }
            }

            if (sign == null) {
                return;
            }

            Player p = e.getPlayer();
           
            if(!sign.isValid()) {
                p.sendMessage(prefix + ChatColor.RED
                        + "An unexpected error has occured when removing this WorldSpawns sign. Please check the console for the error log, and send this to the plugin developer.");
                main.getSigns().remove(sign);
                main.consoleMessage(
                        "&cWSSign found with invalid SignType. This is an unexpected error, and should never occur. Please report this to plugin developer. Invalid WSSign is deleted.");
                return;
            }

            if (sign.getType() == SignType.SPAWN) {
                if (!p.hasPermission(new Permissions().sign_spawn_use)) {
                    p.sendMessage(noperm.replaceAll("%type%", "spawn"));
                    return;
                }

                String worldname = p.getLocation().getWorld().getName();
                String xs = settings.getSpawns().getString("spawns." + worldname + ".x");
                String ys = settings.getSpawns().getString("spawns." + worldname + ".y");
                String zs = settings.getSpawns().getString("spawns." + worldname + ".z");
                String yaws = settings.getSpawns().getString("spawns." + worldname + ".yaw");
                String pitchs = settings.getSpawns().getString("spawns." + worldname + ".pitch");
                if (xs == null || ys == null || zs == null || yaws == null || pitchs == null) {
                    p.sendMessage(prefix + color(Lang.COMMAND_SPAWN_CURRENT_NULL.toString()));
                    return;
                } else {
                    if (main.getConfig().getBoolean("settings.teleportDelay")) {
                        double x = p.getLocation().getX();
                        double y = p.getLocation().getY();
                        double z = p.getLocation().getZ();
                        ScheduleSpawnTP spawn = new ScheduleSpawnTP(main, p,
                                main.getConfig().getInt("settings.teleportDelaySpawn"), worldname, x, y, z);
                        spawn.setTaskId(Bukkit.getScheduler().scheduleSyncRepeatingTask(main, spawn, 0, 20));
                    } else {
                        World w = main.getServer().getWorld(worldname);
                        double x = settings.getSpawns().getDouble("spawns." + worldname + ".x");
                        double y = settings.getSpawns().getDouble("spawns." + worldname + ".y");
                        double z = settings.getSpawns().getDouble("spawns." + worldname + ".z");
                        float yaw = settings.getSpawns().getInt("spawns." + worldname + ".yaw");
                        float pitch = settings.getSpawns().getInt("spawns." + worldname + ".pitch");
                        p.teleport(new Location(w, x, y, z, yaw, pitch));
                        SpawnFirework firework = new SpawnFirework(p, main);
                        if (main.getConfig().getBoolean("firework.enable")) {
                            if (main.getConfig().getBoolean("firework.random")) {
                                firework.spawnRandomFirework();
                            } else {
                                firework.spawnFirework();
                            }
                        }

                        p.sendMessage(prefix + color(Lang.COMMAND_SPAWN_TELEPORT.toString()));
                        if (enableSounds()) {
                            p.playSound(p.getLocation(), Sound.ENTITY_ENDERMEN_TELEPORT, 10F, 1.0F);
                        }
                    }

                    return;
                }
            }

            if (sign.getType() == SignType.FSPAWN) {
                if (!p.hasPermission(new Permissions().sign_fspawn_use)) {
                    p.sendMessage(noperm.replaceAll("%type%", "fspawn"));
                    return;
                }

                String worldname = p.getLocation().getWorld().getName();
                String xs = settings.getSpawns().getString("spawns." + worldname + ".x");
                String ys = settings.getSpawns().getString("spawns." + worldname + ".y");
                String zs = settings.getSpawns().getString("spawns." + worldname + ".z");
                String yaws = settings.getSpawns().getString("spawns." + worldname + ".yaw");
                String pitchs = settings.getSpawns().getString("spawns." + worldname + ".pitch");
                if (xs == null || ys == null || zs == null || yaws == null || pitchs == null) {
                    p.sendMessage(prefix + color(Lang.COMMAND_SPAWN_CURRENT_NULL.toString()));
                    return;
                } else {
                    World w = main.getServer().getWorld(worldname);
                    double x = settings.getSpawns().getDouble("spawns." + worldname + ".x");
                    double y = settings.getSpawns().getDouble("spawns." + worldname + ".y");
                    double z = settings.getSpawns().getDouble("spawns." + worldname + ".z");
                    float yaw = settings.getSpawns().getInt("spawns." + worldname + ".yaw");
                    float pitch = settings.getSpawns().getInt("spawns." + worldname + ".pitch");
                    p.teleport(new Location(w, x, y, z, yaw, pitch));
                    SpawnFirework firework = new SpawnFirework(p, main);
                    if (main.getConfig().getBoolean("firework.enable")) {
                        if (main.getConfig().getBoolean("firework.random")) {
                            firework.spawnRandomFirework();
                        } else {
                            firework.spawnFirework();
                        }
                    }

                    p.sendMessage(prefix + color(Lang.COMMAND_SPAWN_TELEPORT.toString()));
                    if (enableSounds()) {
                        p.playSound(p.getLocation(), Sound.ENTITY_ENDERMEN_TELEPORT, 10F, 1.0F);
                    }
                    return;
                }
            }

            if (sign.getType() == SignType.HUB) {
                if (!p.hasPermission(new Permissions().sign_hub_use)) {
                    p.sendMessage(noperm.replaceAll("%type%", "hub"));
                    return;
                }

                double x = p.getLocation().getX();
                double y = p.getLocation().getY();
                double z = p.getLocation().getZ();
                ScheduleHubTP hub = new ScheduleHubTP(main, p, main.getConfig().getInt("settings.teleportDelayHub"), x, y, z);
                hub.setTaskId(Bukkit.getScheduler().scheduleSyncRepeatingTask(main, hub, 0, 20));
                return;
            }

            if (sign.getType() == SignType.FHUB) {
                if (!p.hasPermission(new Permissions().sign_fhub_use)) {
                    p.sendMessage(noperm.replaceAll("%type%", "fhub"));
                    return;
                }

                World w = main.getServer().getWorld(settings.getHub().getString("hub.world"));
                double x2 = settings.getHub().getDouble("hub.x");
                double y2 = settings.getHub().getDouble("hub.y");
                double z2 = settings.getHub().getDouble("hub.z");
                float yaw = settings.getHub().getInt("hub.yaw");
                float pitch = settings.getHub().getInt("hub.pitch");
                p.teleport(new Location(w, x2, y2, z2, yaw, pitch));
                SpawnFirework firework = new SpawnFirework(p, main);
                if (main.getConfig().getBoolean("firework.enable")) {
                    if (main.getConfig().getBoolean("firework.random")) {
                        firework.spawnRandomFirework();
                    } else {
                        firework.spawnFirework();
                    }
                }

                p.sendMessage(prefix + color(Lang.COMMAND_HUB_TELEPORTED.toString()));
                if (enableSounds()) {
                    p.playSound(p.getLocation(), Sound.ENTITY_ENDERMEN_TELEPORT, 10F, 1.0F);
                }
                return;
            }
        }
     
  6. ciz

    ciz

    Take a look at what I posted, it will work.
     
  7. I have attempted this before by creating a local List in the 'WSSignCreate' class, which the method of I posted in the original post, and then, whenever a new one is added, override it with the List in my 'Main' class. However, the same problem kept occurring.
     
  8. Did you try printing out the elements in list before and after you add another element?
     
  9. ciz

    ciz

    If this is not solved later I will write it out for you.
     
  10. I've done this, and these are the results.

    Before adding:
    After adding:
    And even after removing one, and adding one again:
    So it seems that, at the moment, they do get added, but do not get recognized or something (?). Also, they do not get removed properly, but that's because they do not get added to the List in the first place, so handling the removal of them is not functioning as well.
     
  11. How are you saving/loading these signs? It looks like you're directly storing the object as a string or something like that. You should serialize the locations, store them somewhere, then load and deserialize those values back into a location. You can get the block from there and add it to the list.
     
  12. I do save their location in the form of an ID, consisting of the following:
    Code (Java):
    String id = world + "@" + Integer.valueOf((int) loc.getX()) + ";" + Integer.valueOf((int) loc.getY()) + ";" + Integer.valueOf((int) loc.getZ());
    Which is then disected upon startup with this:
    Code (Java):
    for(int i = 0; i < signList.size(); i++) {
                String s = signList.get(i);
                if(s.contains("@")) {
                    String[] s1 = s.split("@");
                    if(s1[1].contains(";")) {
                        String[] s2 = s1[1].split(";");
                     
                        String world = s1[0];
                        World w = main.getServer().getWorld(world);
                        int x = Integer.valueOf(s2[0]);
                        int y = Integer.valueOf(s2[1]);
                        int z = Integer.valueOf(s2[2]);
                     
                        String id = world + "@" + x + ";" + y + ";" + z;
                     
                        Block b = w.getBlockAt(x, y, z);
                     
                        if(b == null || !(b.getType() == Material.SIGN || b.getType() == Material.SIGN_POST || b.getType() == Material.WALL_SIGN)) {
                            filec.set("signs." + id, null);
                            continue;
                        }
                     
                        WSSign sign = new WSSign((Sign) b.getState(), SignType.valueOf(filec.getString("signs." + id + ".type")));
                     
                        if(sign.getType() == SignType.SPAWN || sign.getType() == SignType.FSPAWN) {
                            sign.setSpawnWorld(main.getServer().getWorld(filec.getString("signs" + id + ".world")));
                        } else {
                            sign.setSpawnWorld(null);
                        }
                     
                        signs.add(sign);
                    }
                }
            }
    As how they are being stored in the List does not really matter to me. As long as the instance of them is stored, my Saver class should be able to get the ID of the sign, and then save it to the file.
     
    • Like Like x 1
  13. I've been tinkering around again, and it seems the elements are being added. Printing out the List before and after adding signs shows that they do indeed get added to the list. Now the real problem seems to be that my way of iterating through the list does not recognize the other sign types as elements or something.

    Here's the beginning of my PlayerInteractEvent method that I use to check if a WSSign is actually involved in the event:
    Code (Java):
    if (!(e.getClickedBlock().getType() == Material.SIGN || e.getClickedBlock().getType() == Material.SIGN_POST
            || e.getClickedBlock().getType() == Material.WALL_SIGN)) {
        return;
    }

    if (e.getAction() != Action.RIGHT_CLICK_BLOCK) {
        return;
    }

    Sign s = (Sign) e.getClickedBlock().getState();
    World sw = s.getWorld();
    int sx = s.getX();
    int sy = s.getY();
    int sz = s.getZ();

    WSSign sign = null;

    for (Iterator<WSSign> i = main.getSigns().iterator(); i.hasNext();) {
        WSSign ws = i.next();
        World wsw = ws.getWorld();
        int wsx = ws.getX();
        int wsy = ws.getY();
        int wsz = ws.getZ();

        if (wsw == sw && sx == wsx && sy == wsy && sz == wsz) {
            sign = ws;
            break;
        } else {
            continue;
        }
    }

    if (sign == null) {
        return;
    }

    Player p = e.getPlayer();
       
    if(!sign.isValid()) {
        p.sendMessage(prefix + ChatColor.RED
                + "An unexpected error has occured when removing this WorldSpawns sign. Please check the console for the error log, and send this to the plugin developer.");
        main.getSigns().remove(sign);
        main.consoleMessage(
                "&cWSSign found with invalid SignType. This is an unexpected error, and should never occur. Please report this to plugin developer. Invalid WSSign is deleted.");
        return;
    }