timbru31

Untitled

Jan 12th, 2013
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 6.90 KB | None | 0 0
  1. package me.plugin.ptweaks;
  2.  
  3. import org.bukkit.Chunk;
  4. import org.bukkit.Location;
  5. import org.bukkit.World;
  6. import org.bukkit.entity.Entity;
  7. import org.bukkit.entity.LivingEntity;
  8. import org.bukkit.event.EventHandler;
  9. import org.bukkit.event.Listener;
  10. import org.bukkit.event.player.PlayerMoveEvent;
  11. import org.bukkit.event.world.ChunkLoadEvent;
  12. import org.bukkit.event.world.ChunkUnloadEvent;
  13.  
  14. import java.util.Iterator;
  15. import java.util.LinkedHashMap;
  16. import java.util.Map;
  17. import java.util.Map.Entry;
  18.  
  19. public class ChunkPersistance implements Runnable, Listener {
  20.     private PerformanceTweaks mPlugin;
  21.     private Thread mThread = new Thread(this);
  22.     private int mLifeTime = 100000;
  23.     private int mPruneTime = 3000;
  24.     private int mSpawnChunkRadius = 128;
  25.     private int mViewDistanceChunks = 10;
  26.     // I believe a LinkedHashMap suits best, because it keeps the order like it was added, so better looping
  27.     // Since we want to remove our first entry generally... --> Found faster
  28.     // If you know what I mean ;) --> http://stackoverflow.com/a/2889800
  29.     private LinkedHashMap<String, Long> mChunks = new LinkedHashMap<String, Long>();
  30.     // --->     private LinkedHashMap<String, Integer> lastAmountOfChunks = new LinkedHashMap<String, Integer>();
  31.  
  32.     public ChunkPersistance(PerformanceTweaks plugin) {
  33.         mPlugin = plugin;
  34.         // Register the events
  35.         plugin.getServer().getPluginManager().registerEvents(this, plugin);
  36.     }
  37.  
  38.     public void onEnable() {
  39.         // Get the config values
  40.         mLifeTime = mPlugin.chunkPersistance.getInt("lifetime", 100000);
  41.         mPruneTime = mPlugin.chunkPersistance.getInt("prune", 3000);
  42.         mSpawnChunkRadius = mPlugin.chunkPersistance.getInt("spawnChunkRadius", 128);
  43.         mViewDistanceChunks = mPlugin.chunkPersistance.getInt("viewDistanceChunks", 10);
  44.  
  45.         // Log the information
  46.         mPlugin.getLogger().info(String.format("Chunk Life Time: %dms", mLifeTime));
  47.         mPlugin.getLogger().info(String.format("Chunk Prune Time: %dms",mPruneTime));
  48.  
  49.         //      long time = System.currentTimeMillis();
  50.         //      // Go through all worlds
  51.         //      for (World world : mPlugin.getServer().getWorlds()) {
  52.         //          // Go through all chunks
  53.         //          for (Chunk chunk : world.getLoadedChunks()) {
  54.         //              // Don't add if spawn chunk
  55.         //              if (!isSpawnChunk(chunk)) {
  56.         //                  String s = chunk.getWorld().getName() + ";" + chunk.getX() + ";" + chunk.getZ();
  57.         //                  mChunks.put(s, time);
  58.         //              }
  59.         //          }
  60.         //      }
  61.  
  62.         mThread.start();
  63.     }
  64.  
  65.     public void onDisable() {
  66.         // Disable the Thread again
  67.         if (mThread.isAlive()) mThread.interrupt();
  68.         // Iterate through HashMap
  69.         for (Map.Entry<String, Long> entry: mChunks.entrySet()) {
  70.             String[] key = entry.getKey().split(";");
  71.             String w = key[0];
  72.             int x = Integer.valueOf(key[1]);
  73.             int z = Integer.valueOf(key[2]);
  74.             World world = mPlugin.getServer().getWorld(w);
  75.             // If the chunk is loaded, unload!
  76.             if (world.isChunkLoaded(x, z))  world.unloadChunk(x, z);
  77.         }
  78.         clear();
  79.  
  80.     }
  81.  
  82.     @EventHandler
  83.     public void onChunkLoad(ChunkLoadEvent event) {
  84.         // If its NO spawn chunk
  85.         if (!isSpawnChunk(event.getChunk())) {
  86.             Chunk c = event.getChunk();
  87.             // Better use only the name of the world
  88.             String s = c.getWorld().getName() + ";" + c.getX() + ";" + c.getZ();
  89.             // Save the chunk with a time
  90.             mChunks.put(s, System.currentTimeMillis());
  91.         }
  92.     }
  93.  
  94.     @EventHandler
  95.     public void onChunkUnload(ChunkUnloadEvent event) {
  96.         // Never unload a spawn chunk!
  97.         if (isSpawnChunk(event.getChunk())) {
  98.             event.setCancelled(true);
  99.             return;
  100.         }
  101.  
  102.         Chunk c = event.getChunk();
  103.         String s = c.getWorld().getName() + ";" + c.getX() + ";" + c.getZ();
  104.  
  105.         // Check if the chunk is on our list
  106.         if (!mChunks.containsKey(s)) {
  107.             return;
  108.         }
  109.  
  110.         long age = System.currentTimeMillis() - mChunks.get(s);
  111.         // If the age is not "old" enough, keep the chunk loaded
  112.         if (age < mLifeTime) {
  113.             event.setCancelled(true);
  114.         }
  115.         // Else remove it from the list
  116.         else {
  117.             mChunks.remove(s);
  118.         }
  119.     }
  120.  
  121.     @EventHandler
  122.     public void onPlayerMove(PlayerMoveEvent event) {
  123.         long time = System.currentTimeMillis();
  124.         // I changed the code so that the chunks around the player are added/updated is customizable
  125.  
  126.         // Use minecraft method ;)
  127.         int x = event.getPlayer().getLocation().getChunk().getX();
  128.         int z = event.getPlayer().getLocation().getChunk().getZ();
  129.  
  130.         // Get all da chunks in a radius
  131.         World world = event.getPlayer().getLocation().getWorld();
  132.         for (int a = 0; a < mViewDistanceChunks; a++) {
  133.             for (int b = 0; b < mViewDistanceChunks; b++) {
  134.                 Chunk chunk = world.getChunkAt(x + a, z + b);
  135.                 if (!isSpawnChunk(chunk)) {
  136.                     String s = chunk.getWorld().getName() + ";" + chunk.getX() + ";" + chunk.getZ();
  137.                     mChunks.put(s, time);
  138.                 }
  139.             }
  140.         }
  141.     }
  142.  
  143.     public void clear() {
  144.         mChunks.clear();
  145.     }
  146.    
  147.     private void restartThread() {
  148.         mThread.interrupt();
  149.         mThread = new Thread(this);
  150.         mThread.start();
  151.     }
  152.  
  153.     // Check is a chunk is a spawn chunk
  154.     private boolean isSpawnChunk(Chunk chunk) {
  155.         Location spawn = chunk.getWorld().getSpawnLocation();
  156.         // Get absolute value, so we can check just with bigger than 128
  157.         int x = Math.abs(chunk.getX() - spawn.getBlockX());
  158.         int z = Math.abs(chunk.getZ() - spawn.getBlockZ());
  159.         return (x <= mSpawnChunkRadius) && (z <= mSpawnChunkRadius);
  160.     }
  161.  
  162.     public void run() {
  163.         try {
  164.             while (!mThread.isInterrupted()) {
  165.                 System.out.println("Called");
  166.                 try {
  167.                     Thread.sleep(mPruneTime);
  168.                 }
  169.                 catch (InterruptedException e) {
  170.                     Thread.currentThread().interrupt();
  171.                     return;
  172.                 }
  173.                 // Get current time
  174.                 long timeNow = System.currentTimeMillis();
  175.  
  176.                 // Iterate through HashMap
  177.                 Iterator<Entry<String, Long>> iterator = mChunks.entrySet().iterator();
  178.                 while (iterator.hasNext()) {
  179.                     Map.Entry<String, Long> entry = iterator.next();
  180.                     String[] key = entry.getKey().split(";");
  181.                     String w = key[0];
  182.                     World world = mPlugin.getServer().getWorld(w);
  183.                     // ---> if (lastAmountOfChunks.containsKey(w) && lastAmountOfChunks.get(w) == world.getLoadedChunks().length) continue;
  184.                     long time = entry.getValue();
  185.                     long age = timeNow - time;
  186.                     // If the liftTime of the chunk is reached
  187.                     if (age >= mLifeTime) {
  188.                         int x = Integer.valueOf(key[1]);
  189.                         int z = Integer.valueOf(key[2]);
  190.                         // If the chunk is loaded, unload!
  191.                         if (world.isChunkLoaded(x, z)) {
  192.                             // Check for players --> DO NOT UNLOAD then
  193.                             boolean playerFound = false;
  194.                             for (Entity e : world.getChunkAt(x, z).getEntities()) {
  195.                                 if (e instanceof LivingEntity) {
  196.                                     playerFound = true;
  197.                                 }
  198.                             }
  199.                             if (!playerFound) {
  200.                                 world.unloadChunk(x, z);
  201.                                 iterator.remove();
  202.                             }
  203.                         }
  204.                     }
  205.                     // ---> lastAmountOfChunks.put(w, world.getLoadedChunks().length);
  206.                 }
  207.                
  208.             }
  209.         }
  210.         // Good to listen, since anything could happen, and I'm not sure what exactly (:
  211.         catch (Exception e) {
  212.             e.printStackTrace();
  213.             restartThread();
  214.         }
  215.     }
  216. }
Advertisement
Add Comment
Please, Sign In to add comment