Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package me.plugin.ptweaks;
- import org.bukkit.Chunk;
- import org.bukkit.Location;
- import org.bukkit.World;
- import org.bukkit.entity.Entity;
- import org.bukkit.entity.LivingEntity;
- import org.bukkit.event.EventHandler;
- import org.bukkit.event.Listener;
- import org.bukkit.event.player.PlayerMoveEvent;
- import org.bukkit.event.world.ChunkLoadEvent;
- import org.bukkit.event.world.ChunkUnloadEvent;
- import java.util.Iterator;
- import java.util.LinkedHashMap;
- import java.util.Map;
- import java.util.Map.Entry;
- public class ChunkPersistance implements Runnable, Listener {
- private PerformanceTweaks mPlugin;
- private Thread mThread = new Thread(this);
- private int mLifeTime = 100000;
- private int mPruneTime = 3000;
- private int mSpawnChunkRadius = 128;
- private int mViewDistanceChunks = 10;
- // I believe a LinkedHashMap suits best, because it keeps the order like it was added, so better looping
- // Since we want to remove our first entry generally... --> Found faster
- // If you know what I mean ;) --> http://stackoverflow.com/a/2889800
- private LinkedHashMap<String, Long> mChunks = new LinkedHashMap<String, Long>();
- // ---> private LinkedHashMap<String, Integer> lastAmountOfChunks = new LinkedHashMap<String, Integer>();
- public ChunkPersistance(PerformanceTweaks plugin) {
- mPlugin = plugin;
- // Register the events
- plugin.getServer().getPluginManager().registerEvents(this, plugin);
- }
- public void onEnable() {
- // Get the config values
- mLifeTime = mPlugin.chunkPersistance.getInt("lifetime", 100000);
- mPruneTime = mPlugin.chunkPersistance.getInt("prune", 3000);
- mSpawnChunkRadius = mPlugin.chunkPersistance.getInt("spawnChunkRadius", 128);
- mViewDistanceChunks = mPlugin.chunkPersistance.getInt("viewDistanceChunks", 10);
- // Log the information
- mPlugin.getLogger().info(String.format("Chunk Life Time: %dms", mLifeTime));
- mPlugin.getLogger().info(String.format("Chunk Prune Time: %dms",mPruneTime));
- // long time = System.currentTimeMillis();
- // // Go through all worlds
- // for (World world : mPlugin.getServer().getWorlds()) {
- // // Go through all chunks
- // for (Chunk chunk : world.getLoadedChunks()) {
- // // Don't add if spawn chunk
- // if (!isSpawnChunk(chunk)) {
- // String s = chunk.getWorld().getName() + ";" + chunk.getX() + ";" + chunk.getZ();
- // mChunks.put(s, time);
- // }
- // }
- // }
- mThread.start();
- }
- public void onDisable() {
- // Disable the Thread again
- if (mThread.isAlive()) mThread.interrupt();
- // Iterate through HashMap
- for (Map.Entry<String, Long> entry: mChunks.entrySet()) {
- String[] key = entry.getKey().split(";");
- String w = key[0];
- int x = Integer.valueOf(key[1]);
- int z = Integer.valueOf(key[2]);
- World world = mPlugin.getServer().getWorld(w);
- // If the chunk is loaded, unload!
- if (world.isChunkLoaded(x, z)) world.unloadChunk(x, z);
- }
- clear();
- }
- @EventHandler
- public void onChunkLoad(ChunkLoadEvent event) {
- // If its NO spawn chunk
- if (!isSpawnChunk(event.getChunk())) {
- Chunk c = event.getChunk();
- // Better use only the name of the world
- String s = c.getWorld().getName() + ";" + c.getX() + ";" + c.getZ();
- // Save the chunk with a time
- mChunks.put(s, System.currentTimeMillis());
- }
- }
- @EventHandler
- public void onChunkUnload(ChunkUnloadEvent event) {
- // Never unload a spawn chunk!
- if (isSpawnChunk(event.getChunk())) {
- event.setCancelled(true);
- return;
- }
- Chunk c = event.getChunk();
- String s = c.getWorld().getName() + ";" + c.getX() + ";" + c.getZ();
- // Check if the chunk is on our list
- if (!mChunks.containsKey(s)) {
- return;
- }
- long age = System.currentTimeMillis() - mChunks.get(s);
- // If the age is not "old" enough, keep the chunk loaded
- if (age < mLifeTime) {
- event.setCancelled(true);
- }
- // Else remove it from the list
- else {
- mChunks.remove(s);
- }
- }
- @EventHandler
- public void onPlayerMove(PlayerMoveEvent event) {
- long time = System.currentTimeMillis();
- // I changed the code so that the chunks around the player are added/updated is customizable
- // Use minecraft method ;)
- int x = event.getPlayer().getLocation().getChunk().getX();
- int z = event.getPlayer().getLocation().getChunk().getZ();
- // Get all da chunks in a radius
- World world = event.getPlayer().getLocation().getWorld();
- for (int a = 0; a < mViewDistanceChunks; a++) {
- for (int b = 0; b < mViewDistanceChunks; b++) {
- Chunk chunk = world.getChunkAt(x + a, z + b);
- if (!isSpawnChunk(chunk)) {
- String s = chunk.getWorld().getName() + ";" + chunk.getX() + ";" + chunk.getZ();
- mChunks.put(s, time);
- }
- }
- }
- }
- public void clear() {
- mChunks.clear();
- }
- private void restartThread() {
- mThread.interrupt();
- mThread = new Thread(this);
- mThread.start();
- }
- // Check is a chunk is a spawn chunk
- private boolean isSpawnChunk(Chunk chunk) {
- Location spawn = chunk.getWorld().getSpawnLocation();
- // Get absolute value, so we can check just with bigger than 128
- int x = Math.abs(chunk.getX() - spawn.getBlockX());
- int z = Math.abs(chunk.getZ() - spawn.getBlockZ());
- return (x <= mSpawnChunkRadius) && (z <= mSpawnChunkRadius);
- }
- public void run() {
- try {
- while (!mThread.isInterrupted()) {
- System.out.println("Called");
- try {
- Thread.sleep(mPruneTime);
- }
- catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- return;
- }
- // Get current time
- long timeNow = System.currentTimeMillis();
- // Iterate through HashMap
- Iterator<Entry<String, Long>> iterator = mChunks.entrySet().iterator();
- while (iterator.hasNext()) {
- Map.Entry<String, Long> entry = iterator.next();
- String[] key = entry.getKey().split(";");
- String w = key[0];
- World world = mPlugin.getServer().getWorld(w);
- // ---> if (lastAmountOfChunks.containsKey(w) && lastAmountOfChunks.get(w) == world.getLoadedChunks().length) continue;
- long time = entry.getValue();
- long age = timeNow - time;
- // If the liftTime of the chunk is reached
- if (age >= mLifeTime) {
- int x = Integer.valueOf(key[1]);
- int z = Integer.valueOf(key[2]);
- // If the chunk is loaded, unload!
- if (world.isChunkLoaded(x, z)) {
- // Check for players --> DO NOT UNLOAD then
- boolean playerFound = false;
- for (Entity e : world.getChunkAt(x, z).getEntities()) {
- if (e instanceof LivingEntity) {
- playerFound = true;
- }
- }
- if (!playerFound) {
- world.unloadChunk(x, z);
- iterator.remove();
- }
- }
- }
- // ---> lastAmountOfChunks.put(w, world.getLoadedChunks().length);
- }
- }
- }
- // Good to listen, since anything could happen, and I'm not sure what exactly (:
- catch (Exception e) {
- e.printStackTrace();
- restartThread();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment