Problems with loading a value over reload

Discussion in 'Plugin Development' started by ImpaTheImpaler, Sep 5, 2019.

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

    ImpaTheImpaler

    So I have been trying to get this to work for a while now. Basically, my plugin is a shop plugin, and so far I have it set up where any player in game types a command and right clicks an NPC and a chest to link the two together and create a shop where players will (this part isn't coded yet but it is where it's going) rent the 'stall' off the NPC and place the items in the chest. Everything works so far but for some reason when I reload the server, the hashmap I'm using only saves half of the data. So it remembers that the chest is a shop, but it doesn't remember that the NPC is linked to it. There are no errors, it's just a mistake in the code.

    Here is my code for actually handling the linking:
    Code:
    package shops;
    
    import chests.ChestFunctions;
    import main.Main;
    import org.bukkit.*;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.block.Action;
    import org.bukkit.event.inventory.InventoryOpenEvent;
    import org.bukkit.event.player.PlayerInteractEntityEvent;
    import org.bukkit.event.player.PlayerInteractEvent;
    import org.bukkit.event.player.PlayerQuitEvent;
    import org.bukkit.inventory.EquipmentSlot;
    import org.bukkit.inventory.Inventory;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap;
    
    public class ShopHandler implements Listener {
    
        public static ArrayList<String> link_shop = new ArrayList<String>();
        public static ArrayList<String> delete_shop = new ArrayList<String>();
        public static ConcurrentHashMap<Location, Location> shop = new ConcurrentHashMap<Location, Location>(); // entity loc, chest loc, stored in npc_rent_shops
        public static HashMap<String, Location> player_shop = new HashMap<String, Location>(); // stored in player_shops.yml
        public static HashMap<Player, Location> stored_location = new HashMap<Player, Location>(); // temp location storage
        public static HashMap<String, Integer> shop_time = new HashMap<String, Integer>(); // pl_name, timer
        public static HashMap<String, Inventory> shop_inv = new HashMap<String, Inventory>(); // stored in saved_shops
    
        @EventHandler
        public void onOpen(InventoryOpenEvent e){
            if (delete_shop.contains(e.getPlayer().getName()) || link_shop.contains(e.getPlayer().getName())){
                if (e.getInventory().getName().equalsIgnoreCase("Chest") ||
                    e.getInventory().getName().equalsIgnoreCase("Alder Chest") ||
                    e.getInventory().getName().equalsIgnoreCase("Elm Chest") ||
                        e.getInventory().getName().equalsIgnoreCase("Pine Chest") ||
                        e.getInventory().getName().equalsIgnoreCase("Oak Chest")){
                    e.setCancelled(true);
                }
            }
        }
    
        @EventHandler
        public void onShopCreate2(PlayerInteractEvent e){
            if (e.getHand().equals(EquipmentSlot.HAND)){
                if (e.getAction() == Action.RIGHT_CLICK_BLOCK){
                    if (e.getClickedBlock().getType() == Material.CHEST){
                        e.setCancelled(true);
    
                        if (link_shop.contains(e.getPlayer().getName()) && e.getPlayer().isOp()){
                            if (shop.containsValue(e.getClickedBlock().getLocation())){
                                e.getPlayer().sendMessage(ChatColor.GOLD + "That chest is already linked to a trader.");
                                e.getPlayer().sendMessage(ChatColor.RED + "Creation cancelled.");
                                link_shop.remove(e.getPlayer().getName());
    
                                if (stored_location.containsKey(e.getPlayer())){
                                    stored_location.remove(e.getPlayer());
                                }
    
                            } else {
                                if (!ChestFunctions.isCustomChest(e.getClickedBlock().getLocation())){
    
                                    if (stored_location.containsKey(e.getPlayer())){
                                        shop.put(stored_location.get(e.getPlayer()), e.getClickedBlock().getLocation());
                                        stored_location.remove(e.getPlayer());
                                        e.getPlayer().sendMessage(ChatColor.GREEN + "Shop created.");
                                        e.getPlayer().playSound(e.getPlayer().getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 1F, 1F);
    
                                        ShopFunctions.saveData();
    
                                        Bukkit.getServer().getScheduler().runTaskLater(Main.instance, new Runnable(){
                                            public void run(){
                                                link_shop.remove(e.getPlayer().getName());
                                            }
                                        }, 5L);
    
                                    } else {
                                        stored_location.put(e.getPlayer(), e.getClickedBlock().getLocation());
                                        e.getPlayer().sendMessage(ChatColor.GOLD + "Now right click a trader to create a shop.");
                                    }
                                } else {
                                    e.getPlayer().sendMessage(ChatColor.GOLD + "That chest is a loot chest.");
                                    e.getPlayer().sendMessage(ChatColor.RED + "Creation cancelled.");
                                    link_shop.remove(e.getPlayer().getName());
    
                                    if (stored_location.containsKey(e.getPlayer())){
                                        stored_location.remove(e.getPlayer());
                                    }
                                }
                            }
                        }
    
                        if (delete_shop.contains(e.getPlayer().getName()) && e.getPlayer().isOp()){
                            if (shop.containsValue(e.getClickedBlock().getLocation())){
    
                                    for (Map.Entry<Location, Location> loc : shop.entrySet()){
                                         if (loc.getValue().equals(e.getClickedBlock().getLocation())){
                                             shop.remove(loc.getKey());
                                             shop.remove(loc.getValue());
                                         }
                                    }
    
                                    e.getPlayer().sendMessage(ChatColor.RED + "Shop deleted.");
                                    e.getPlayer().playSound(e.getPlayer().getLocation(), Sound.BLOCK_ANVIL_BREAK, 1F, 1F);
                                    ShopFunctions.saveData();
    
                                    for (Location loc : ShopHandler.shop.keySet()) {
                                    String s = String.valueOf(loc.getWorld().getName()) + "," +
                                            (int) loc.getX() + "," + (int) loc.getY() + "," + (int) loc.getZ();
                                        Bukkit.getConsoleSender().sendMessage(s);
                                    }
    
                                Bukkit.getServer().getScheduler().runTaskLater(Main.instance, new Runnable(){
                                    public void run(){
                                        delete_shop.remove(e.getPlayer().getName());
                                    }
                                }, 5L);
    
    
                            } else {
                                if (ChestFunctions.isCustomChest(e.getClickedBlock().getLocation())){
                                    e.getPlayer().sendMessage(ChatColor.GOLD + "That chest is a loot chest.");
                                    e.getPlayer().sendMessage(ChatColor.RED + "Deletion cancelled.");
                                    delete_shop.remove(e.getPlayer().getName());
    
                                    if (stored_location.containsKey(e.getPlayer())){
                                        stored_location.remove(e.getPlayer());
                                    }
                                } else {
                                    e.getPlayer().sendMessage(ChatColor.GOLD + "That chest is not a shop.");
                                    e.getPlayer().sendMessage(ChatColor.RED + "Deletion cancelled.");
                                    delete_shop.remove(e.getPlayer().getName());
    
                                    if (stored_location.containsKey(e.getPlayer())){
                                        stored_location.remove(e.getPlayer());
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    
        @EventHandler
        public void onQuit(PlayerQuitEvent e){
            if (link_shop.contains(e.getPlayer().getName())){
                link_shop.remove(e.getPlayer().getName());
            }
    
            if (delete_shop.contains(e.getPlayer().getName())){
                link_shop.remove(e.getPlayer().getName());
            }
    
            if (stored_location.containsKey(e.getPlayer())){
                stored_location.remove(e.getPlayer());
            }
        }
    
        @EventHandler
        public void onShopCreate(PlayerInteractEntityEvent e){
            if (e.getRightClicked().getName().equalsIgnoreCase("Trader")){
                if (e.getHand().equals(EquipmentSlot.HAND)) {
                    if (e.getPlayer().isOp()){
                        if (link_shop.contains(e.getPlayer().getName())){
                            if (!shop.containsKey(e.getRightClicked().getLocation())){
                                if (stored_location.containsKey(e.getPlayer())){
                                    shop.put(e.getRightClicked().getLocation(), stored_location.get(e.getPlayer()));
    
                                    Location loc = e.getRightClicked().getLocation();
                                    String s = String.valueOf(loc.getWorld().getName()) + "," +
                                            (int) loc.getX() + "," + (int) loc.getY() + "," + (int) loc.getZ();
                                    Bukkit.getConsoleSender().sendMessage(s);
    
                                    stored_location.remove(e.getPlayer());
                                    link_shop.remove(e.getPlayer().getName());
                                    e.getPlayer().sendMessage(ChatColor.GREEN + "Shop created.");
                                    e.getPlayer().playSound(e.getPlayer().getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 1F, 1F);
                                    ShopFunctions.saveData();
                                } else {
                                    stored_location.put(e.getPlayer(), e.getRightClicked().getLocation());
                                    e.getPlayer().sendMessage(ChatColor.GOLD + "Now right click a chest to create a shop.");
                                }
                            } else {
                                e.getPlayer().sendMessage(ChatColor.GOLD + "This trader is already linked to a shop.");
                                e.getPlayer().sendMessage(ChatColor.RED + "Creation cancelled.");
                                link_shop.remove(e.getPlayer().getName());
    
                                if (stored_location.containsKey(e.getPlayer())){
                                    stored_location.remove(e.getPlayer());
                                }
                            }
    
                        } else if (delete_shop.contains(e.getPlayer().getName())){
                            if (shop.containsKey(e.getRightClicked().getLocation())){
    
                                e.getPlayer().sendMessage(ChatColor.RED + "Shop deleted.");
                                e.getPlayer().playSound(e.getPlayer().getLocation(), Sound.BLOCK_ANVIL_BREAK, 1F, 1F);
                                Location l = shop.get(e.getRightClicked().getLocation());
                                shop.remove(e.getRightClicked().getLocation());
                                shop.remove(l);
                                delete_shop.remove(e.getPlayer().getName());
                                ShopFunctions.saveData();
    
                                for (Location loc : ShopHandler.shop.keySet()) {
                                    String s = String.valueOf(loc.getWorld().getName()) + "," +
                                            (int) loc.getX() + "," + (int) loc.getY() + "," + (int) loc.getZ();
                                    Bukkit.getConsoleSender().sendMessage(s);
                                }
                            } else {
                                e.getPlayer().sendMessage(ChatColor.GOLD + "This trader is not linked to a shop.");
                                e.getPlayer().sendMessage(ChatColor.RED + "Deletion cancelled.");
                                delete_shop.remove(e.getPlayer().getName());
    
                                if (stored_location.containsKey(e.getPlayer())){
                                    stored_location.remove(e.getPlayer());
                                }
                            }
                        }
                    }
                }
            }
        }
    
        public void onLoad(){
            Bukkit.getServer().getPluginManager().registerEvents(this, Main.instance);
            ShopFunctions.loadData();
        }
    
        public void onUnload(){
            ShopFunctions.saveData();
        }
    }
    Here is the code handling the saving - which works completely as it is debugged and it saves and loads perfectly.
    Code:
    package shops;
    
    import main.Main;
    import org.bukkit.Bukkit;
    import org.bukkit.Location;
    import org.bukkit.World;
    import org.bukkit.configuration.file.YamlConfiguration;
    
    import java.io.File;
    import java.io.IOException;
    
    public class ShopFunctions {
    
        public static void saveData() {
            File data = new File(Main.instance.getDataFolder() + "/shops/npc_shops.yml");
            YamlConfiguration config = new YamlConfiguration();
                for (Location loc : ShopHandler.shop.keySet()) {
                    Location loc1 = ShopHandler.shop.get(loc);
    
                    String s = String.valueOf(loc.getWorld().getName()) + "," +
                            (int) loc.getX() + "," + (int) loc.getY() + "," + (int) loc.getZ();
    
                    String s1 = String.valueOf(loc1.getWorld().getName()) + "," +
                            (int) loc1.getX() + "," + (int) loc1.getY() + "," + (int) loc1.getZ();
    
                    config.set(s, s1); // trader loc, chest loc
    
                    if (Main.instance.getDataFolder().exists()){
                        try {
                            config.save(data);
                        } catch (IOException e1) {
                            e1.printStackTrace();
                        }
                    }
                }
        }
    
        public static boolean isShopChest(Location loc){
            if (ShopHandler.shop.containsValue(loc)){
                return true;
            } else { return false; }
        }
    
        public static void loadData() {
            File data = new File(Main.instance.getDataFolder() + "/shops/npc_shops.yml");
            YamlConfiguration config = new YamlConfiguration();
    
            if (Main.instance.getDataFolder().exists()){
                try {
                    config.load(data);
                } catch (Exception e) {
                    e.printStackTrace();
                }
    
                for (String key : config.getKeys(false)) {
                    String[] str = key.split(",");
                    World world = Bukkit.getWorld(str[0]);
                    double x = Double.valueOf(str[1]);
                    double y = Double.valueOf(str[2]);
                    double z = Double.valueOf(str[3]);
                    Location ent = new Location(world, (int) x, (int) y, (int) z);
    
                    String s = config.getString(key);
                    String[] s1 = s.split(",");
    
                    double x1 = Double.valueOf(s1[1]);
                    double y1 = Double.valueOf(s1[2]);
                    double z1 = Double.valueOf(s1[3]);
                    Location chest = new Location(world, (int) x1, (int) y1, (int) z1);
    
                    Bukkit.getServer().getConsoleSender().sendMessage(key);
                    Bukkit.getServer().getConsoleSender().sendMessage(s);
    
                    ShopHandler.shop.put(ent, chest);
                }
            }
        }
    
        public static void savePlayerData(String pl){
            pl = pl.toLowerCase();
        }
    
        public static void deletePlayerData(String pl){
            pl = pl.toLowerCase();
        }
    }
    
     
  2. Which hashMap is the issue?
    Try adding some more debug
     
  3. Offline

    ImpaTheImpaler

    It’s the shop hashmap, and I have done loads of debugging and just can’t seem to find the issue.
     
  4. At which point do you notice that the hashMap isn't complete? I just see two shop-create functions which judging by the name and event should not be called after you restart and get the problem.
     
  5. Offline

    ImpaTheImpaler

    Well after restart it’s set to load straight back into the hashmap if you look at where it’s saved into confit.Its after restart that the problem occurs, but I debugged all the saving and it was fine.
     
  6. Yeah but you said
    How do you know that? What does not work ingame?
     
  7. Offline

    ImpaTheImpaler

    So the bug is that the chest saves, but the NPC doesn’t.
     
  8. So then what are the results from debugging the loadData()? Since that is the only place where shop gets modified (again judging by the method names)
     
  9. Offline

    ImpaTheImpaler

    When I debug it from there, the locations debug the correct locations and it does when it reloads as i have it debugging after reload, but when you check it in game it says that the NPCs aren’t linked to any chest.
     
  10. Could you show me the part of the code where it says that they aren't linked?

    EDIT: okay I got an idea of what's going on. You save the location of the chest which is okay but you also save the Location of the villager, which is an entity, which probably moves. I'm not sure how you get the Villager from its Location (so please post this code) but the Villager could just have turned his head and so his location isn't identical with the saved one anymore
     
    Last edited: Sep 9, 2019
  11. Offline

    ImpaTheImpaler

    But it isn't a villager, it's a NPC from citizens which stays static, and the code of getting its location is in the original post in the first code section. The reason I said it was a trader is because that's what the NPC is called.
     
  12. Yeah and how do you target the NPC when you click on a chest? (for reading his trades I guess)
     
    Last edited: Sep 9, 2019
  13. Offline

    ImpaTheImpaler

    I don't think you understand how this works, there are no trades yet - it has nothing to do with villagers. Basically when a player types /create_shop he right clicks an NPC (seperate from a villager) and then he right clicks a chest, or he can do it the other way round where he clicks on a chest and then an NPC. It saves both locations of the chest and the NPC to a hashmap which is stored on config. It works before I reload, but after I reload, it saves the locations perfectly BUT then if I try to debug it and create another shop, when I click on the chest it remembers that it is a shop, but when I right click the trader NPC it acts like the trader isn't already linked to a chest. I am starting to wonder whether when it reloads and the citizens respawn, that they respawn at the same location but different double values.
     
  14. That's what I said before.
    So the problem occurs in the playerInteractEntityEvent is right? And there 'shop' does not contain the location of the Trader as a key?

    If that's the case print all contents of the hashmap and compare them to the current location of the clicked trader
     
Thread Status:
Not open for further replies.

Share This Page