1.15.2 Reducing the CPU of reading config files

Discussion in 'Spigot Plugin Development' started by Donkelyn, Jul 19, 2020.

  1. Heya, I'm developing a new plugin based around skills. I'll drop some pseudocode below so you can get an understanding.


    - EntityDamageEntityEvent
    If instanceofplayer
    Read meta of players weapon
    Get type of player weapon (axe, sword ect)
    Read the players unique config file and find their level in the weapon type
    Switch case depending on the weapon meta which compares whether the weapon level is higher than the players level (if they are a lower level then event is cancelled)
    Run damage calculation
    Inside damage calculation
    Loop 3 times to read the players equipped skills
    Change the damage and add extra effects based on skills
    return damage
    then e.setDamage the new calculated damage

    This is all functional exactly as I want it except for the fact that the server CPU usage increases ridiculously when players are fighting. Are there any ways to streamline this to make it function the same but faster?
     
  2. I would just suggest to not read the info from the config every time. You can create some kind of player stats class that holds the values as long as the player is online.
     
  3. The plugin creates a mem cache of the config then saves when the server shuts.
    Reading from a file also shouldnt be super taxing on your cpu.
    Could we see your code?

    For my RPG plugin for my personal project, I keep a class with data of the user. The DB is only read when the player loads in, and saved every 2 mins and when the player leaves. I use MongoDB but you can apply the same concept to yml files.
     
  4. So I would read the files when the player joins, then save them as a seperate class file, then every 3 minutes or so I update the files with the class files, or whenever the player logs out or changes their loaded skills. Wouldn't this cause a lag spike every 3 minutes? Also do you have any sample code to use when creating the class with the player data?
     
  5. You technically don't even need to save them every 3 minutes. Ideally you would only have to save them whenever the server reloads/restarts. I would recommend saving them whenever the player disconnects. It shouldn't cause a lag spike unless you're using a very terrible server.
     
  6. How do I go about making classes for each individual player when the login?
     
  7. You would make some sort of Data class that would act as an object per player. I would strongly recommend learning Java before attempting something as complicated as this.
     
    • Agree Agree x 1
  8. I've currently done one semester of java at uni but I don't think we covered something like this
     
  9. So this is my PlayerStats class:

    Code (Text):
    public class PlayerStats {

        private int playerRankSwords;
        private int playerRankAxes;
       
        public PlayerStats (int playerRankSwords, int playerRankAxes) {
            this.playerRankSwords = playerRankSwords;
            this.playerRankAxes = playerRankAxes;
           
            }
       
        public int getPlayerRankSwords(){
            return playerRankSwords;
        }
       
        public int getPlayerRankAxes() {
            return playerRankAxes;
        }
    }
    This is what I put in my Manager Class
    Code (Text):

    private PlayerStats ppmd;
        private static PlayerStats playerFile;
    Then this is what I use when a player joins :
    Code (Text):

    @EventHandler
        public void configLoader(PlayerJoinEvent e) {
            Player p = e.getPlayer();
            String playerID = p.getUniqueId().toString();
           
            File userdata = new File(plugin.getDataFolder(), File.separator + "PlayerDatabase");
            File f = new File(userdata, File.separator + playerID + ".yml");
            FileConfiguration playerData = YamlConfiguration.loadConfiguration(f);
           
            int playerRankSword = playerData.getInt("ranks.sword");
            int playerRankAxe = playerData.getInt("ranks.axe");
           
            playerFile = new PlayerStats(playerRankSword, playerRankAxe);
        }
    I haven't tried this yet. But is this what you mean or am I doing this horribly wrong
     
  10. Something like that yes, however I would definitely separate the loading and creation of your object. Assuming basics, you could define a load(YamlConfiguration) and from there get the values. The class itself should be responsible of loading/saving the data. You should make a separate class only for creating the object itself. SOLID principles.
     
  11. So would it be something like:
    Code (Text):
    @EventHandler

        public void configLoader(PlayerJoinEvent e) {
            Player p = e.getPlayer();
            playerFile = new PlayerStats(p);
        }
    And then:

    Code (Text):
    public class PlayerStats {

        Main plugin;
       
        public PlayerStats(Main instance) {
            plugin = instance;
        }
        private int playerRankSword;
        private int playerRankAxe;
       
        public PlayerStats (Player p) {
            String playerID = p.getUniqueId().toString();
           
            File userdata = new File(plugin.getDataFolder(), File.separator + "PlayerDatabase");
            File f = new File(userdata, File.separator + playerID + ".yml");
            FileConfiguration playerData = YamlConfiguration.loadConfiguration(f);
           
            playerRankSword = playerData.getInt("ranks.sword");
            playerRankAxe = playerData.getInt("ranks.axe");
           
            }
       
        public int getPlayerRankSwords(){
            return playerRankSword;
        }
       
        public int getPlayerRankAxes() {
            return playerRankAxe;
        }
    }
     
  12. Periodical saving just means I have saved player data incase the server crashed or anything- I'd rather a player lose 2 minutes of data instead of 1 hours worth.
    Plus database hooks are usually run on a separate thread, which wouldnt affect your server.