NPC save

Discussion in 'Plugin Development' started by KyllianGamer, Dec 27, 2018.

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

    KyllianGamer

    I'm working on a plugin with custom inventories with npc's. The inventory gets saved and it all works but if I reload the server the npc's just respawn correctly, but when I stop the server and start him again the NPC's will not come back. Is there any way of fixing this by maybe looping all the NPC's and saving their data to the config when the plugin shuts down?
     
  2. I would indeed suggest saving their data on shutdown, and loading them again on startup and spawning them again with spawnEntity().
     
  3. Offline

    The_Spaceman

    how so you summon in the NPCs?
    When with commands: save all needed data in config. when onEnable recreate all the NPCs with the saved data
     
  4. Offline

    KyllianGamer

    Yes that is litteraly what I said but I know how to like loop them all and put information in a config but how do I save it on a easy way instead of saving litteraly everything that has to do with that npc and how do I load it?
     
  5. I think saving to a file in this format is adequate (if this is what you mean):

    Code:
    entity1:
      type: (e.g. 'VILLAGER')
      customname: (custom name)
      location: (serialized location)
    
    If neseccary, include things such as passengers, vehicles etc..

    I suggest making a class which handles saving and loading the NPC's. If you would like to know how, just ask! :)
     
  6. Offline

    KyllianGamer

    Sure that actually would be very nice @Kevinzuman22 :D
     
  7. @KyllianGamer
    Alright. I've finished the example saver. I have not tested it whatsoever, so I recommend making backups of important data of your server.

    I've attempted to save the vehicles as well, but unfortunately there is no way to set an Entity as a vehicle of another Entity through code.
    ExampleSaver.java (open)

    Code:
    public class ExampleSaver {
    
        private Main main = Main.getInstance();
    
        private ArrayList<Creature> creatures;
    
        private File file;
        private FileConfiguration filec;
    
        public ExampleSaver() {}
    
        public void save() {
            creatures = null;
    
            for(int i = 0; i < creatures.size(); i++) {
                Creature npc = creatures.get(i);
      
                String id = npc.getUniqueId().toString();
      
                filec.set("npcs." + id + ".type", npc.getType().name());
                filec.set("npcs." + id + ".customname", npc.getCustomName());
                filec.set("npcs." + id + ".location", npc.getLocation().serialize());
      
                /*
                OPTIONAL: inlcude this as well if you'd also like to save the NPC's passengers.
                REMOVE THIS IF YOU DO NOT REQUIRE IT.
                */
      
                filec.set("npcs." + id + ".passengers", serializePassengers(npc.getPassengers()));
            }
    
            try {
                filec.save(file);
            } catch (IOException e) {
                e.printStackTrace();
                return;
            }
    
            creatures.clear();
            reload();
        }
    
        public List<Creature> load() {
            creatures = new ArrayList<Creature>();
            ArrayList<String> npcList = (ArrayList<String>) filec.getStringList("npcs");
            if(npcList == null) {
                filec.createSection("npcs");
            }
    
            for(String s : filec.getStringList("npcs")) {
                UUID id = UUID.fromString(s);
      
                Location loc = Location.deserialize(filec.getConfigurationSection("npcs." + s + ".location").getValues(false));
      
                Entity entity = Bukkit.getEntity(id);
      
      
                if(entity == null) {
                    entity = loc.getWorld().spawnEntity(loc, EntityType.valueOf(filec.getString("npcs." + s + ".type")));
                }
      
                /*
                OPTIONAL: inlcude this as well if you'd also like to save the NPC's passengers.
                REMOVE THIS IF YOU DO NOT REQUIRE IT.
                */
      
                for(Entity e : deserializePassengers(filec.getString("npcs." + s + ".passengers"))) {
                    entity.addPassenger(e);
                }
      
            }
    
            return creatures;
        }
    
        private String serializePassengers(List<Entity> passengers) {
            String s = "";
    
            for(int i = 0; i < passengers.size(); i++) {
                Entity e = passengers.get(i);
      
                UUID id = e.getUniqueId();
                EntityType t = e.getType();
                String n = e.getCustomName();
      
                if(i == passengers.size() - 1) {
                    s += id.toString() + ";" + t.name() + "," + n;
                } else {
                    s += id.toString() + ";" + t.name() + "," + n + ";";
                }
            }
    
            return s;
        }
    
        private  List<Entity> deserializePassengers(String s) {
            List<Entity> passengers = new ArrayList<Entity>();
    
            String[] s1 = s.split(";");
    
            for(String str : s1) {
                String[] s2 = str.split(",");
      
                UUID id = UUID.fromString(s2[0]);
                EntityType t = EntityType.valueOf(s2[1]);
                String n = s1[2];
      
                Entity e = Bukkit.getServer().getEntity(id);
      
                passengers.add(e);
            }
    
            return passengers;
        }
    
        public void reload() {
            YamlConfiguration conf = YamlConfiguration.loadConfiguration(file);
            this.filec = conf;
        }
    
        public void clear() {
            filec.set("npcs", null);
        }
    
        public void setup() {
            File file = new File(main.getDataFolder(), File.separator + "npcs.yml");
    
            if (!file.exists()) {
                try {
                    main.getDataFolder().mkdir();
                    file.mkdir();
                } catch (Exception e) {
                    e.printStackTrace();
                    main.getLogger().severe("Couldn't create npcs save file.");
                    main.getLogger().severe("This is a fatal error. Now disabling");
                      main.getServer().getPluginManager().disablePlugin(main);
                }
            }
    
            YamlConfiguration conf = YamlConfiguration.loadConfiguration(file);
    
            if(conf.getConfigurationSection("npcs") == null) {
                conf.createSection("npcs");
            }
    
            this.file = file;
            this.filec = conf;
    
            try {
                conf.save(file);
            } catch (IOException e) {
                e.printStackTrace();
            }
    
        }
    
        public ArrayList<Creature> getNPCs() {
            return creatures;
        }
    
        public FileConfiguration getSaver() {
            return filec;
        }
    }

    After creating a class containing that code, you just create an instance in your plugin's main class file like this:
    Code:
    private ExampleSaver saver;
    
    public ExampleSaver getSaver() {
        return saver;
    }
    and add this to your onEnable():
    Code:
    saver = new ExampleSaver();
    saver.setup();
    Now you can save all the NPC's in your onDisable() like this:
    Code:
    saver.save();
    and load them again in your onEnable() with this (NOTE: make sure to only use this piece of code after 'saver.setup()' is used, otherwise errors will occur):
    Code:
    List<Creature> npcs = saver.load();
    Let me know if you're running into any problems. But also let me know if everything's working fine! :)
     
    Last edited: Dec 29, 2018
Thread Status:
Not open for further replies.

Share This Page