Storing the coordinates of an entity (villager) in minecraft

Discussion in 'Plugin Development' started by caledonian26, Jan 31, 2023.

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

    caledonian26

    Hey all,

    I have the following code which runs successfully and allows me to store the coordinates of players every second in minecraft.

    Code:
    public class Main extends JavaPlugin implements Listener
    {
        boolean stopRepeater;
        HashMap<UUID, BukkitTask> tasks = new HashMap<>();
        private File dataFolder;
    
        public void onEnable() {
            Bukkit.getServer().getPluginManager().registerEvents(this,this);
            getLogger().info("HELLO! WELCOME TO THE TRACKER PLUGIN");
            dataFolder = new File(getDataFolder(), "data");
            dataFolder.mkdirs();
        }
    
        @EventHandler
        public void onLogin(final PlayerJoinEvent event) {
            final Player thePlayer = event.getPlayer();
            this.stopRepeater = true;
            final Location playerSpawnLocation = thePlayer.getLocation();
            getLogger().info("Welcome " + thePlayer.getName() + ". Your current position is: " + playerSpawnLocation); 
            BukkitTask task = getServer().getScheduler().runTaskTimer(this, () -> {
                if(this.stopRepeater) {
                    this.logToFile(thePlayer, thePlayer.getLocation());
                }
            }, 0L, 20L);
            tasks.put(thePlayer.getUniqueId(),task);}
    
        @EventHandler
        public void onQuit(final PlayerQuitEvent event) {
            Player thePlayer = event.getPlayer();
            if(!thePlayer.isOnline()) {
                this.stopRepeater = false;
                getLogger().info(String.valueOf(event.getPlayer().getName()) + " has left the game");
                BukkitTask task = tasks.remove(thePlayer.getUniqueId());
                if(task != null) {
                   task.cancel();
                }
            }
        }
    
        public void logToFile(final Player currentPlayer, final Location playerCurrentLocation) {
            try {
                String content = String.valueOf(new SimpleDateFormat("dd-MM-yyyy HH:mm:ss").format(new Date())) + " CurrentLocation(x,y,z): " + playerCurrentLocation.getBlockX() + " " + playerCurrentLocation.getBlockY() + " " + playerCurrentLocation.getBlockZ() + "\n";
                if (!getDataFolder().exists()) {
                      getDataFolder().mkdirs();
                    }
                final File file = new File(dataFolder, currentPlayer.getName() + ".log");
                if (!file.exists()) {
                    file.createNewFile();
                }
                Files.write(file.toPath(),content.getBytes(StandardCharsets.UTF_8),StandardOpenOption.APPEND);
            } catch (Exception e) {
                e.printStackTrace();
            }
         }
    }
    
    However, I want to adapt this code to also store the locations of an entity (extract the coordinates of) - a non-human minecraft character known as a 'villager' - , which I have called 'villager', as this entity represents the 'villager' character in minecraft.

    Would the following amended code be the correct way to do this?

    Code:
     
    package newestfile.here.newestplugin;
    
    import java.util.UUID;
    import java.nio.charset.StandardCharsets;
    import java.nio.file.StandardOpenOption;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.HashMap;
    import java.io.File;
    import org.bukkit.event.player.PlayerQuitEvent;
    import org.bukkit.event.EventHandler;
    import org.bukkit.entity.Entity;
    import org.bukkit.entity.Player;
    import org.bukkit.Location;
    import org.bukkit.event.player.PlayerInteractEntityEvent;
    import org.bukkit.event.player.PlayerJoinEvent;
    import org.bukkit.Bukkit;
    import org.bukkit.event.Listener;
    import org.bukkit.plugin.java.JavaPlugin;
    import org.bukkit.scheduler.BukkitTask;
    import java.nio.file.Files; 
    
    public class Main extends JavaPlugin implements Listener
    {
        boolean stopRepeater;
        HashMap<UUID, BukkitTask> tasks = new HashMap<>();
    
        private File dataFolder;
       
        public void onEnable() {
            Bukkit.getServer().getPluginManager().registerEvents(this,this);
            getLogger().info("HELLO! WELCOME TO THE TRACKER PLUGIN");
            dataFolder = new File(getDataFolder(), "data"); 
            dataFolder.mkdirs();
        }
       
        @EventHandler
        public void onLogin(final PlayerJoinEvent event) {
            final Player thePlayer = event.getPlayer();
            this.stopRepeater = true;
            final Location playerSpawnLocation = thePlayer.getLocation();
            getLogger().info("Welcome " + thePlayer.getName() + ". Your current position is: " + playerSpawnLocation); 
            BukkitTask task = getServer().getScheduler().runTaskTimer(this, () -> {
                if(this.stopRepeater) {
                    this.logToFile(thePlayer, thePlayer.getLocation());
                }
            }, 0L, 20L);
            tasks.put(thePlayer.getUniqueId(),task);}
    
        @EventHandler
        public void onQuit(final PlayerQuitEvent event) {
            Player thePlayer = event.getPlayer();
            if(!thePlayer.isOnline()) {
                this.stopRepeater = false;
                getLogger().info(String.valueOf(event.getPlayer().getName()) + " has left the game");
                BukkitTask task = tasks.remove(thePlayer.getUniqueId());
                if(task != null) {
                   task.cancel();
                }
            }
        }
    
        public void logToFile(final Player currentPlayer, final Location playerCurrentLocation) {
            try {
                String content = String.valueOf(new SimpleDateFormat("dd-MM-yyyy HH:mm:ss").format(new Date())) + " CurrentLocation(x,y,z): " + playerCurrentLocation.getBlockX() + " " + playerCurrentLocation.getBlockY() + " " + playerCurrentLocation.getBlockZ() + "\n";
                if (!getDataFolder().exists()) {
                      getDataFolder().mkdirs();
                    }
                final File file = new File(dataFolder, currentPlayer.getName() + ".log");
                if (!file.exists()) {
                    file.createNewFile();
                }
                Files.write(file.toPath(),content.getBytes(StandardCharsets.UTF_8),StandardOpenOption.APPEND);
            } catch (Exception e) {
                e.printStackTrace();
            }
         }
       
        @EventHandler
        public void onEntityInteract(PlayerInteractEntityEvent event) {
            final Entity minecharacter = event.getRightClicked(); 
            this.stopRepeater = true; 
            BukkitTask task = getServer().getScheduler().runTaskTimer(this, () -> {
                if(this.stopRepeater) {
                    this.logToFile(minecharacter, minecharacter.getLocation());
                }
            }, 0L, 20L);
            tasks.put(minecharacter.getUniqueId(),task);}
    
        public void logToFile(final Entity minecraftcharacter, final Location minecraftcharacterlocation) {
            try {
                String content = String.valueOf(new SimpleDateFormat("dd-MM-yyyy HH:mm:ss").format(new Date())) + "Character name: " + minecraftcharacter.getName() + " VillagerCurrentLocation(x,y,z): " + minecraftcharacterlocation.getBlockX() + " " + minecraftcharacterlocation.getBlockY() + " " + minecraftcharacterlocation.getBlockZ() + "\n";
                if (!getDataFolder().exists()) {
                      getDataFolder().mkdirs();
                    }
                final File file = new File(dataFolder, minecraftcharacter.getName() + ".log");
                if (!file.exists()) {
                    file.createNewFile();
                }
                Files.write(file.toPath(),content.getBytes(StandardCharsets.UTF_8),StandardOpenOption.APPEND);
            } catch (Exception e) {
                e.printStackTrace();
            }
         }
    }
    
    I would be so grateful for a helping hand!
     
    Last edited: Jan 31, 2023
  2. Offline

    timtower Administrator Administrator Moderator

  3. Offline

    caledonian26

    Yes, it works (I edited the original code above)!! Thanks so much for your support :)
     
  4. Offline

    Strahan

    You had better hope this server won't get very busy; file IO is expensive and you're doing a lot of it. You are also really wasting disk space. You don't need a player location every second; what you need is player location with a time index. For example, say a player steps AFK to use the bathroom and their character stands there idly for 10 minutes. You now have spent 29k for data that can 100% be accurately recreated within 49 bytes - using only 0.17% of the space :)

    What'd I'd do is cache to RAM and just dump periodically, and the data I'd be caching would be only updated when the player actually traverses a block.

    In other words, what I mean is for example this dataset:
    Code:
    01-02-2023 22:00:00 CurrentLocation(x,y,z): -102 67 192
    01-02-2023 22:00:01 CurrentLocation(x,y,z): -102 67 196
    01-02-2023 22:00:02 CurrentLocation(x,y,z): -102 67 197
    01-02-2023 22:00:03 CurrentLocation(x,y,z): -102 67 197
    01-02-2023 22:00:04 CurrentLocation(x,y,z): -102 67 197
    01-02-2023 22:00:05 CurrentLocation(x,y,z): -102 67 197
    01-02-2023 22:00:06 CurrentLocation(x,y,z): -102 67 197
    01-02-2023 22:00:07 CurrentLocation(x,y,z): -102 67 197
    01-02-2023 22:00:08 CurrentLocation(x,y,z): -102 67 197
    01-02-2023 22:00:09 CurrentLocation(x,y,z): -102 67 197
    01-02-2023 22:00:10 CurrentLocation(x,y,z): -102 67 197
    01-02-2023 22:00:11 CurrentLocation(x,y,z): -102 67 197
    01-02-2023 22:00:12 CurrentLocation(x,y,z): -102 67 197
    01-02-2023 22:00:13 CurrentLocation(x,y,z): -102 67 197
    01-02-2023 22:00:14 CurrentLocation(x,y,z): -102 67 197
    01-02-2023 22:00:15 CurrentLocation(x,y,z): -102 67 197
    01-02-2023 22:00:16 CurrentLocation(x,y,z): -102 67 197
    01-02-2023 22:00:17 CurrentLocation(x,y,z): -102 67 197
    01-02-2023 22:00:18 CurrentLocation(x,y,z): -102 67 197
    01-02-2023 22:00:19 CurrentLocation(x,y,z): -102 67 197
    01-02-2023 22:00:20 CurrentLocation(x,y,z): -102 67 197
    01-02-2023 22:00:21 CurrentLocation(x,y,z): -102 67 197
    01-02-2023 22:00:22 CurrentLocation(x,y,z): -102 67 197
    01-02-2023 22:00:23 CurrentLocation(x,y,z): -102 67 197
    01-02-2023 22:00:24 CurrentLocation(x,y,z): -102 67 197
    01-02-2023 22:00:25 CurrentLocation(x,y,z): -102 67 199
    Offers exactly the same information as this dataset:
    Code:
    01-02-2023 22:00:00 CurrentLocation(x,y,z): -102 67 192
    01-02-2023 22:00:01 CurrentLocation(x,y,z): -102 67 196
    01-02-2023 22:00:02 CurrentLocation(x,y,z): -102 67 197
    01-02-2023 22:00:25 CurrentLocation(x,y,z): -102 67 199
    But requires only 16% of the storage capacity of the first set.
     
Thread Status:
Not open for further replies.

Share This Page