mirror of
https://github.com/mcMMO-Dev/mcMMO.git
synced 2025-06-28 03:34:43 +02:00
Merge branch 'master' of github.com:mcMMO-Dev/mcMMO
This commit is contained in:
@ -8,7 +8,7 @@ import org.bukkit.inventory.ItemStack;
|
||||
import com.gmail.nossr50.config.Config;
|
||||
import com.gmail.nossr50.datatypes.PlayerProfile;
|
||||
import com.gmail.nossr50.locale.LocaleLoader;
|
||||
import com.gmail.nossr50.skills.SkillTools;
|
||||
import com.gmail.nossr50.skills.utilities.SkillTools;
|
||||
|
||||
public final class ChimaeraWing {
|
||||
private ChimaeraWing() {}
|
||||
|
@ -5,7 +5,7 @@ import org.bukkit.entity.Player;
|
||||
import com.gmail.nossr50.config.Config;
|
||||
import com.gmail.nossr50.datatypes.PlayerProfile;
|
||||
import com.gmail.nossr50.locale.LocaleLoader;
|
||||
import com.gmail.nossr50.skills.SkillType;
|
||||
import com.gmail.nossr50.skills.utilities.SkillType;
|
||||
|
||||
public final class Hardcore {
|
||||
public static double statLossPercentage = Config.getInstance().getHardcoreDeathStatPenaltyPercentage();
|
||||
|
@ -10,7 +10,7 @@ import java.util.List;
|
||||
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import com.gmail.nossr50.datatypes.PlayerStat;
|
||||
import com.gmail.nossr50.skills.SkillType;
|
||||
import com.gmail.nossr50.skills.utilities.SkillType;
|
||||
|
||||
public final class Leaderboard {
|
||||
private static HashMap<SkillType, List<PlayerStat>> playerStatHash = new HashMap<SkillType, List<PlayerStat>>();
|
||||
|
@ -5,7 +5,7 @@ import org.bukkit.plugin.PluginDescriptionFile;
|
||||
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import com.gmail.nossr50.locale.LocaleLoader;
|
||||
import com.gmail.nossr50.skills.SkillType;
|
||||
import com.gmail.nossr50.skills.utilities.SkillType;
|
||||
|
||||
public final class Motd {
|
||||
private static final String perkPrefix = LocaleLoader.getString("MOTD.PerksPrefix");
|
||||
|
@ -3,7 +3,7 @@ package com.gmail.nossr50.util;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.gmail.nossr50.skills.SkillType;
|
||||
import com.gmail.nossr50.skills.utilities.SkillType;
|
||||
|
||||
public final class Permissions {
|
||||
private Permissions() {}
|
||||
@ -243,6 +243,10 @@ public final class Permissions {
|
||||
return hasPermission(player, "mcmmo.ability.fishing.fishermansdiet");
|
||||
}
|
||||
|
||||
public static boolean fishingVanillaXPBoost(Player player) {
|
||||
return hasPermission(player, "mcmmo.ability.fishing.vanillaxpboost");
|
||||
}
|
||||
|
||||
/*
|
||||
* MCMMO.ABILITY.MINING.*
|
||||
*/
|
||||
|
@ -1,151 +0,0 @@
|
||||
package com.gmail.nossr50.util.blockmeta;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
public interface ChunkletManager {
|
||||
/**
|
||||
* Loads a specific chunklet
|
||||
*
|
||||
* @param cx Chunklet X coordinate that needs to be loaded
|
||||
* @param cy Chunklet Y coordinate that needs to be loaded
|
||||
* @param cz Chunklet Z coordinate that needs to be loaded
|
||||
* @param world World that the chunklet needs to be loaded in
|
||||
*/
|
||||
public void loadChunklet(int cx, int cy, int cz, World world);
|
||||
|
||||
/**
|
||||
* Unload a specific chunklet
|
||||
*
|
||||
* @param cx Chunklet X coordinate that needs to be unloaded
|
||||
* @param cy Chunklet Y coordinate that needs to be unloaded
|
||||
* @param cz Chunklet Z coordinate that needs to be unloaded
|
||||
* @param world World that the chunklet needs to be unloaded from
|
||||
*/
|
||||
public void unloadChunklet(int cx, int cy, int cz, World world);
|
||||
|
||||
/**
|
||||
* Load a given Chunk's Chunklet data
|
||||
*
|
||||
* @param cx Chunk X coordinate that is to be loaded
|
||||
* @param cz Chunk Z coordinate that is to be loaded
|
||||
* @param world World that the Chunk is in
|
||||
*/
|
||||
public void loadChunk(int cx, int cz, World world);
|
||||
|
||||
/**
|
||||
* Unload a given Chunk's Chunklet data
|
||||
*
|
||||
* @param cx Chunk X coordinate that is to be unloaded
|
||||
* @param cz Chunk Z coordinate that is to be unloaded
|
||||
* @param world World that the Chunk is in
|
||||
*/
|
||||
public void unloadChunk(int cx, int cz, World world);
|
||||
|
||||
/**
|
||||
* Informs the ChunkletManager a chunk is loaded
|
||||
*
|
||||
* @param cx Chunk X coordinate that is loaded
|
||||
* @param cz Chunk Z coordinate that is loaded
|
||||
* @param world World that the chunk was loaded in
|
||||
*/
|
||||
public void chunkLoaded(int cx, int cz, World world);
|
||||
|
||||
/**
|
||||
* Informs the ChunkletManager a chunk is unloaded
|
||||
*
|
||||
* @param cx Chunk X coordinate that is unloaded
|
||||
* @param cz Chunk Z coordinate that is unloaded
|
||||
* @param world World that the chunk was unloaded in
|
||||
*/
|
||||
public void chunkUnloaded(int cx, int cz, World world);
|
||||
|
||||
/**
|
||||
* Save all ChunkletStores related to the given world
|
||||
*
|
||||
* @param world World to save
|
||||
*/
|
||||
public void saveWorld(World world);
|
||||
|
||||
/**
|
||||
* Unload all ChunkletStores from memory related to the given world after saving them
|
||||
*
|
||||
* @param world World to unload
|
||||
*/
|
||||
public void unloadWorld(World world);
|
||||
|
||||
/**
|
||||
* Load all ChunkletStores from all loaded chunks from this world into memory
|
||||
*
|
||||
* @param world World to load
|
||||
*/
|
||||
public void loadWorld(World world);
|
||||
|
||||
/**
|
||||
* Save all ChunkletStores
|
||||
*/
|
||||
public void saveAll();
|
||||
|
||||
/**
|
||||
* Unload all ChunkletStores after saving them
|
||||
*/
|
||||
public void unloadAll();
|
||||
|
||||
/**
|
||||
* Check to see if a given location is set to true
|
||||
*
|
||||
* @param x X coordinate to check
|
||||
* @param y Y coordinate to check
|
||||
* @param z Z coordinate to check
|
||||
* @param world World to check in
|
||||
* @return true if the given location is set to true, false if otherwise
|
||||
*/
|
||||
public boolean isTrue(int x, int y, int z, World world);
|
||||
|
||||
/**
|
||||
* Check to see if a given block location is set to true
|
||||
*
|
||||
* @param block Block location to check
|
||||
* @return true if the given block location is set to true, false if otherwise
|
||||
*/
|
||||
public boolean isTrue(Block block);
|
||||
|
||||
/**
|
||||
* Set a given location to true, should create stores as necessary if the location does not exist
|
||||
*
|
||||
* @param x X coordinate to set
|
||||
* @param y Y coordinate to set
|
||||
* @param z Z coordinate to set
|
||||
* @param world World to set in
|
||||
*/
|
||||
public void setTrue(int x, int y, int z, World world);
|
||||
|
||||
/**
|
||||
* Set a given block location to true, should create stores as necessary if the location does not exist
|
||||
*
|
||||
* @param block Block location to set
|
||||
*/
|
||||
public void setTrue(Block block);
|
||||
|
||||
/**
|
||||
* Set a given location to false, should not create stores if one does not exist for the given location
|
||||
*
|
||||
* @param x X coordinate to set
|
||||
* @param y Y coordinate to set
|
||||
* @param z Z coordinate to set
|
||||
* @param world World to set in
|
||||
*/
|
||||
public void setFalse(int x, int y, int z, World world);
|
||||
|
||||
/**
|
||||
* Set a given block location to false, should not create stores if one does not exist for the given location
|
||||
*
|
||||
* @param block Block location to set
|
||||
*/
|
||||
public void setFalse(Block block);
|
||||
|
||||
/**
|
||||
* Delete any ChunkletStores that are empty
|
||||
*/
|
||||
public void cleanUp();
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
package com.gmail.nossr50.util.blockmeta;
|
||||
|
||||
import com.gmail.nossr50.config.HiddenConfig;
|
||||
|
||||
public class ChunkletManagerFactory {
|
||||
public static ChunkletManager getChunkletManager() {
|
||||
HiddenConfig hConfig = HiddenConfig.getInstance();
|
||||
|
||||
if (hConfig.getChunkletsEnabled()) {
|
||||
return new HashChunkletManager();
|
||||
}
|
||||
|
||||
return new NullChunkletManager();
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
package com.gmail.nossr50.util.blockmeta;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* A ChunkletStore should be responsible for a 16x16x64 area of data
|
||||
*/
|
||||
public interface ChunkletStore extends Serializable {
|
||||
/**
|
||||
* Checks the value at the given coordinates
|
||||
*
|
||||
* @param x x coordinate in current chunklet
|
||||
* @param y y coordinate in current chunklet
|
||||
* @param z z coordinate in current chunklet
|
||||
* @return true if the value is true at the given coordinates, false if otherwise
|
||||
*/
|
||||
public boolean isTrue(int x, int y, int z);
|
||||
|
||||
/**
|
||||
* Set the value to true at the given coordinates
|
||||
*
|
||||
* @param x x coordinate in current chunklet
|
||||
* @param y y coordinate in current chunklet
|
||||
* @param z z coordinate in current chunklet
|
||||
*/
|
||||
public void setTrue(int x, int y, int z);
|
||||
|
||||
/**
|
||||
* Set the value to false at the given coordinates
|
||||
*
|
||||
* @param x x coordinate in current chunklet
|
||||
* @param y y coordinate in current chunklet
|
||||
* @param z z coordinate in current chunklet
|
||||
*/
|
||||
public void setFalse(int x, int y, int z);
|
||||
|
||||
/**
|
||||
* @return true if all values in the chunklet are false, false if otherwise
|
||||
*/
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Set all values in this ChunkletStore to the values from another provided ChunkletStore
|
||||
*
|
||||
* @param otherStore Another ChunkletStore that this one should copy all data from
|
||||
*/
|
||||
public void copyFrom(ChunkletStore otherStore);
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
package com.gmail.nossr50.util.blockmeta;
|
||||
|
||||
public class ChunkletStoreFactory {
|
||||
protected static ChunkletStore getChunkletStore() {
|
||||
// TODO: Add in loading from config what type of store we want.
|
||||
return new PrimitiveExChunkletStore();
|
||||
}
|
||||
}
|
@ -1,385 +0,0 @@
|
||||
package com.gmail.nossr50.util.blockmeta;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.StreamCorruptedException;
|
||||
import java.io.UTFDataFormatException;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
public class HashChunkletManager implements ChunkletManager {
|
||||
public HashMap<String, ChunkletStore> store = new HashMap<String, ChunkletStore>();
|
||||
|
||||
@Override
|
||||
public void loadChunklet(int cx, int cy, int cz, World world) {
|
||||
File dataDir = new File(world.getWorldFolder(), "mcmmo_data");
|
||||
File cxDir = new File(dataDir, "" + cx);
|
||||
if (!cxDir.exists()) return;
|
||||
File czDir = new File(cxDir, "" + cz);
|
||||
if (!czDir.exists()) return;
|
||||
File yFile = new File(czDir, "" + cy);
|
||||
if (!yFile.exists()) return;
|
||||
|
||||
ChunkletStore in = deserializeChunkletStore(yFile);
|
||||
if (in != null) {
|
||||
store.put(world.getName() + "," + cx + "," + cz + "," + cy, in);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unloadChunklet(int cx, int cy, int cz, World world) {
|
||||
File dataDir = new File(world.getWorldFolder(), "mcmmo_data");
|
||||
if (store.containsKey(world.getName() + "," + cx + "," + cz + "," + cy)) {
|
||||
File cxDir = new File(dataDir, "" + cx);
|
||||
if (!cxDir.exists()) cxDir.mkdir();
|
||||
File czDir = new File(cxDir, "" + cz);
|
||||
if (!czDir.exists()) czDir.mkdir();
|
||||
File yFile = new File(czDir, "" + cy);
|
||||
|
||||
ChunkletStore out = store.get(world.getName() + "," + cx + "," + cz + "," + cy);
|
||||
serializeChunkletStore(out, yFile);
|
||||
store.remove(world.getName() + "," + cx + "," + cz + "," + cy);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadChunk(int cx, int cz, World world) {
|
||||
File dataDir = new File(world.getWorldFolder(), "mcmmo_data");
|
||||
File cxDir = new File(dataDir, "" + cx);
|
||||
if (!cxDir.exists()) return;
|
||||
File czDir = new File(cxDir, "" + cz);
|
||||
if (!czDir.exists()) return;
|
||||
|
||||
for (int y = 0; y < 4; y++) {
|
||||
File yFile = new File(czDir, "" + y);
|
||||
if (!yFile.exists()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ChunkletStore in = deserializeChunkletStore(yFile);
|
||||
if (in != null) {
|
||||
store.put(world.getName() + "," + cx + "," + cz + "," + y, in);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unloadChunk(int cx, int cz, World world) {
|
||||
File dataDir = new File(world.getWorldFolder(), "mcmmo_data");
|
||||
|
||||
for (int y = 0; y < 4; y++) {
|
||||
if (store.containsKey(world.getName() + "," + cx + "," + cz + "," + y)) {
|
||||
File cxDir = new File(dataDir, "" + cx);
|
||||
if (!cxDir.exists()) cxDir.mkdir();
|
||||
File czDir = new File(cxDir, "" + cz);
|
||||
if (!czDir.exists()) czDir.mkdir();
|
||||
File yFile = new File(czDir, "" + y);
|
||||
|
||||
ChunkletStore out = store.get(world.getName() + "," + cx + "," + cz + "," + y);
|
||||
serializeChunkletStore(out, yFile);
|
||||
store.remove(world.getName() + "," + cx + "," + cz + "," + y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void chunkLoaded(int cx, int cz, World world) {
|
||||
//loadChunk(cx, cz, world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void chunkUnloaded(int cx, int cz, World world) {
|
||||
unloadChunk(cx, cx, world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveWorld(World world) {
|
||||
String worldName = world.getName();
|
||||
File dataDir = new File(world.getWorldFolder(), "mcmmo_data");
|
||||
if (!dataDir.exists())
|
||||
dataDir.mkdirs();
|
||||
|
||||
for (String key : store.keySet()) {
|
||||
String[] info = key.split(",");
|
||||
if (worldName.equals(info[0])) {
|
||||
File cxDir = new File(dataDir, "" + info[1]);
|
||||
if (!cxDir.exists()) cxDir.mkdir();
|
||||
File czDir = new File(cxDir, "" + info[2]);
|
||||
if (!czDir.exists()) czDir.mkdir();
|
||||
|
||||
File yFile = new File(czDir, "" + info[3]);
|
||||
serializeChunkletStore(store.get(key), yFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unloadWorld(World world) {
|
||||
saveWorld(world);
|
||||
|
||||
String worldName = world.getName();
|
||||
|
||||
for (String key : store.keySet()) {
|
||||
String tempWorldName = key.split(",")[0];
|
||||
if (tempWorldName.equals(worldName)) {
|
||||
store.remove(key);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWorld(World world) {
|
||||
//for (Chunk chunk : world.getLoadedChunks()) {
|
||||
// this.chunkLoaded(chunk.getX(), chunk.getZ(), world);
|
||||
//}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveAll() {
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
saveWorld(world);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unloadAll() {
|
||||
saveAll();
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
unloadWorld(world);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTrue(int x, int y, int z, World world) {
|
||||
int cx = x / 16;
|
||||
int cz = z / 16;
|
||||
int cy = y / 64;
|
||||
String key = world.getName() + "," + cx + "," + cz + "," + cy;
|
||||
|
||||
if (!store.containsKey(key)) {
|
||||
loadChunklet(cx, cy, cz, world);
|
||||
}
|
||||
|
||||
if (!store.containsKey(key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ChunkletStore check = store.get(world.getName() + "," + cx + "," + cz + "," + cy);
|
||||
int ix = Math.abs(x) % 16;
|
||||
int iz = Math.abs(z) % 16;
|
||||
int iy = Math.abs(y) % 64;
|
||||
|
||||
return check.isTrue(ix, iy, iz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTrue(Block block) {
|
||||
return isTrue(block.getX(), block.getY(), block.getZ(), block.getWorld());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTrue(int x, int y, int z, World world) {
|
||||
int cx = x / 16;
|
||||
int cz = z / 16;
|
||||
int cy = y / 64;
|
||||
|
||||
int ix = Math.abs(x) % 16;
|
||||
int iz = Math.abs(z) % 16;
|
||||
int iy = Math.abs(y) % 64;
|
||||
|
||||
String key = world.getName() + "," + cx + "," + cz + "," + cy;
|
||||
|
||||
if (!store.containsKey(key)) {
|
||||
loadChunklet(cx, cy, cz, world);
|
||||
}
|
||||
|
||||
ChunkletStore cStore = store.get(key);
|
||||
|
||||
if (cStore == null) {
|
||||
cStore = ChunkletStoreFactory.getChunkletStore();
|
||||
|
||||
store.put(world.getName() + "," + cx + "," + cz + "," + cy, cStore);
|
||||
}
|
||||
|
||||
cStore.setTrue(ix, iy, iz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTrue(Block block) {
|
||||
setTrue(block.getX(), block.getY(), block.getZ(), block.getWorld());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFalse(int x, int y, int z, World world) {
|
||||
int cx = x / 16;
|
||||
int cz = z / 16;
|
||||
int cy = y / 64;
|
||||
|
||||
int ix = Math.abs(x) % 16;
|
||||
int iz = Math.abs(z) % 16;
|
||||
int iy = Math.abs(y) % 64;
|
||||
|
||||
String key = world.getName() + "," + cx + "," + cz + "," + cy;
|
||||
|
||||
if (!store.containsKey(key)) {
|
||||
loadChunklet(cx, cy, cz, world);
|
||||
}
|
||||
|
||||
ChunkletStore cStore = store.get(key);
|
||||
|
||||
if (cStore == null) {
|
||||
return; //No need to make a store for something we will be setting to false
|
||||
}
|
||||
|
||||
cStore.setFalse(ix, iy, iz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFalse(Block block) {
|
||||
setFalse(block.getX(), block.getY(), block.getZ(), block.getWorld());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanUp() {
|
||||
for (String key : store.keySet()) {
|
||||
if (store.get(key).isEmpty()) {
|
||||
String[] info = key.split(",");
|
||||
File dataDir = new File(Bukkit.getWorld(info[0]).getWorldFolder(), "mcmmo_data");
|
||||
|
||||
File cxDir = new File(dataDir, "" + info[1]);
|
||||
if (!cxDir.exists()) continue;
|
||||
File czDir = new File(cxDir, "" + info[2]);
|
||||
if (!czDir.exists()) continue;
|
||||
|
||||
File yFile = new File(czDir, "" + info[3]);
|
||||
yFile.delete();
|
||||
|
||||
//Delete empty directories
|
||||
if (czDir.list().length == 0) czDir.delete();
|
||||
if (cxDir.list().length == 0) cxDir.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cStore ChunkletStore to save
|
||||
* @param location Where on the disk to put it
|
||||
*/
|
||||
private void serializeChunkletStore(ChunkletStore cStore, File location) {
|
||||
FileOutputStream fileOut = null;
|
||||
ObjectOutputStream objOut = null;
|
||||
|
||||
try {
|
||||
if (!location.exists())
|
||||
location.createNewFile();
|
||||
fileOut = new FileOutputStream(location);
|
||||
objOut = new ObjectOutputStream(fileOut);
|
||||
objOut.writeObject(cStore);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
finally {
|
||||
if (objOut != null) {
|
||||
try {
|
||||
objOut.flush();
|
||||
objOut.close();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (fileOut != null) {
|
||||
try {
|
||||
fileOut.close();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param location Where on the disk to read from
|
||||
* @return ChunkletStore from the specified location
|
||||
*/
|
||||
private ChunkletStore deserializeChunkletStore(File location) {
|
||||
ChunkletStore storeIn = null;
|
||||
FileInputStream fileIn = null;
|
||||
ObjectInputStream objIn = null;
|
||||
|
||||
try {
|
||||
fileIn = new FileInputStream(location);
|
||||
objIn = new ObjectInputStream(fileIn);
|
||||
storeIn = (ChunkletStore) objIn.readObject();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
if (ex instanceof EOFException) {
|
||||
// EOF should only happen on Chunklets that somehow have been corrupted.
|
||||
//mcMMO.p.getLogger().severe("Chunklet data at " + location.toString() + " could not be read due to an EOFException, data in this area will be lost.");
|
||||
return ChunkletStoreFactory.getChunkletStore();
|
||||
}
|
||||
else if (ex instanceof StreamCorruptedException) {
|
||||
// StreamCorrupted happens when the Chunklet is no good.
|
||||
//mcMMO.p.getLogger().severe("Chunklet data at " + location.toString() + " is corrupted, data in this area will be lost.");
|
||||
return ChunkletStoreFactory.getChunkletStore();
|
||||
}
|
||||
else if (ex instanceof UTFDataFormatException) {
|
||||
// UTF happens when the Chunklet cannot be read or is corrupted
|
||||
//mcMMO.p.getLogger().severe("Chunklet data at " + location.toString() + " could not be read due to an UTFDataFormatException, data in this area will be lost.");
|
||||
return ChunkletStoreFactory.getChunkletStore();
|
||||
}
|
||||
|
||||
ex.printStackTrace();
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
finally {
|
||||
if (objIn != null) {
|
||||
try {
|
||||
objIn.close();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (fileIn != null) {
|
||||
try {
|
||||
fileIn.close();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Make this less messy, as it is, it's kinda... depressing to do it like this.
|
||||
// Might also make a mess when we move to stacks, but at that point I think I will write a new Manager...
|
||||
// IMPORTANT! If ChunkletStoreFactory is going to be returning something other than PrimitiveEx we need to remove this, as it will be breaking time for old maps
|
||||
|
||||
/*
|
||||
if (!(storeIn instanceof PrimitiveExChunkletStore)) {
|
||||
ChunkletStore tempStore = ChunkletStoreFactory.getChunkletStore();
|
||||
if (storeIn != null) {
|
||||
tempStore.copyFrom(storeIn);
|
||||
}
|
||||
storeIn = tempStore;
|
||||
}
|
||||
*/
|
||||
|
||||
return storeIn;
|
||||
}
|
||||
}
|
@ -1,101 +0,0 @@
|
||||
package com.gmail.nossr50.util.blockmeta;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
/**
|
||||
* A ChunkletManager implementation that does nothing and returns false for all checks.
|
||||
*
|
||||
* Useful for turning off Chunklets without actually doing much work
|
||||
*/
|
||||
public class NullChunkletManager implements ChunkletManager {
|
||||
@Override
|
||||
public void loadChunklet(int cx, int cy, int cz, World world) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unloadChunklet(int cx, int cy, int cz, World world) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadChunk(int cx, int cz, World world) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unloadChunk(int cx, int cz, World world) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void chunkLoaded(int cx, int cz, World world) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void chunkUnloaded(int cx, int cz, World world) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveWorld(World world) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unloadWorld(World world) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWorld(World world) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveAll() {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unloadAll() {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTrue(int x, int y, int z, World world) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTrue(Block block) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTrue(int x, int y, int z, World world) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTrue(Block block) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFalse(int x, int y, int z, World world) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFalse(Block block) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanUp() {
|
||||
return;
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
package com.gmail.nossr50.util.blockmeta;
|
||||
|
||||
public class PrimitiveChunkletStore implements ChunkletStore {
|
||||
private static final long serialVersionUID = -3453078050608607478L;
|
||||
|
||||
/** X, Z, Y */
|
||||
public boolean[][][] store = new boolean[16][16][64];
|
||||
|
||||
@Override
|
||||
public boolean isTrue(int x, int y, int z) {
|
||||
return store[x][z][y];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTrue(int x, int y, int z) {
|
||||
store[x][z][y] = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFalse(int x, int y, int z) {
|
||||
store[x][z][y] = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int y = 0; y < 64; y++) {
|
||||
if (store[x][z][y]) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyFrom(ChunkletStore otherStore) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int y = 0; y < 64; y++) {
|
||||
store[x][z][y] = otherStore.isTrue(x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,178 +0,0 @@
|
||||
package com.gmail.nossr50.util.blockmeta;
|
||||
|
||||
import java.io.Externalizable;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectOutput;
|
||||
|
||||
public class PrimitiveExChunkletStore implements ChunkletStore, Externalizable {
|
||||
private static final long serialVersionUID = 8603603827094383873L;
|
||||
|
||||
/** X, Z, Y */
|
||||
public boolean[][][] store = new boolean[16][16][64];
|
||||
|
||||
@Override
|
||||
public boolean isTrue(int x, int y, int z) {
|
||||
return store[x][z][y];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTrue(int x, int y, int z) {
|
||||
store[x][z][y] = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFalse(int x, int y, int z) {
|
||||
store[x][z][y] = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int y = 0; y < 64; y++) {
|
||||
if (store[x][z][y]) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyFrom(ChunkletStore otherStore) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int y = 0; y < 64; y++) {
|
||||
store[x][z][y] = otherStore.isTrue(x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeExternal(ObjectOutput out) throws IOException {
|
||||
byte[] buffer = new byte[2304]; // 2304 is 16*16*9
|
||||
int bufferIndex = 0;
|
||||
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int y = 0; y < 64; y++) {
|
||||
if (store[x][z][y]) {
|
||||
byte[] temp = constructColumn(x, z);
|
||||
|
||||
for (int i = 0; i < 9; i++) {
|
||||
buffer[bufferIndex] = temp[i];
|
||||
bufferIndex++;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out.write(buffer, 0, bufferIndex);
|
||||
out.flush();
|
||||
}
|
||||
|
||||
// For this we assume that store has been initialized to be all false by now
|
||||
@Override
|
||||
public void readExternal(ObjectInput in) throws IOException {
|
||||
byte[] temp = new byte[9];
|
||||
|
||||
// Could probably reorganize this loop to print nasty things if it does not equal 9 or -1
|
||||
while (in.read(temp, 0, 9) == 9) {
|
||||
int x = addressByteX(temp[0]);
|
||||
int z = addressByteZ(temp[0]);
|
||||
boolean[] yColumn = new boolean[64];
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
for (int j = 0; j < 8; j++) {
|
||||
yColumn[j + (i * 8)] = (temp[i + 1] & (1 << j)) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
store[x][z] = yColumn;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The column: An array of 9 bytes which represent all y values for a given (x,z) Chunklet-coordinate
|
||||
*
|
||||
* The first byte is an address byte, this provides the x and z values.
|
||||
* The next 8 bytes are all y values from 0 to 63, with each byte containing 8 bits of true/false data
|
||||
*
|
||||
* Each of these 8 bytes address to a y value from right to left
|
||||
*
|
||||
* Examples:
|
||||
* 00000001 represents that the lowest y value in this byte is true, all others are off
|
||||
* 10000000 represents that the highest y value in this byte is true, all others are off
|
||||
* 10000001 represents that the lowest and highest y values in this byte are true, all others are off
|
||||
*
|
||||
* Full columns:
|
||||
* See comment on Address byte for information on how to use that byte
|
||||
*
|
||||
* Example:
|
||||
* ADDRESS_BYTE 10000000 00000001 00000000 00000000 00000000 00000000 00000000 00000000
|
||||
* - x, z from ADDRESS_BYTE
|
||||
* - The next byte contains data from 0 to 7
|
||||
* - 1 is set in the highest bit position, this is 7 in y coordinate
|
||||
* - The next byte contains data from 8 to 15
|
||||
* - 1 is set in the lowest bit position, this is 8 in the y coordinate
|
||||
* Therefore, for this column: There are true values at (x, 7, z) and (x, 8, z)
|
||||
*/
|
||||
private byte[] constructColumn(int x, int z) {
|
||||
byte[] column = new byte[9];
|
||||
int index = 1;
|
||||
|
||||
column[0] = makeAddressByte(x, z);
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
byte yCompressed = 0x0;
|
||||
int subColumnIndex = 8 * i;
|
||||
int subColumnEnd = subColumnIndex + 8;
|
||||
|
||||
for (int y = subColumnIndex; y < subColumnEnd; y++) {
|
||||
if (store[x][z][y]) {
|
||||
yCompressed |= 1 << (y % 8);
|
||||
}
|
||||
}
|
||||
|
||||
column[index] = yCompressed;
|
||||
index++;
|
||||
}
|
||||
|
||||
return column;
|
||||
}
|
||||
|
||||
/*
|
||||
* The address byte: A single byte which contains x and z values which correspond to the x and z Chunklet-coordinates
|
||||
*
|
||||
* In Chunklet-coordinates, the only valid values are 0-15, so we can fit both into a single byte.
|
||||
*
|
||||
* The top 4 bits of the address byte are for the x value
|
||||
* The bottom 4 bits of the address byte are for the z value
|
||||
*
|
||||
* Examples:
|
||||
* An address byte with a value 00000001 would be split like so:
|
||||
* - x = 0000 = 0
|
||||
* - z = 0001 = 1
|
||||
* => Chunklet coordinates (0, 1)
|
||||
*
|
||||
* 01011111
|
||||
* - x = 0101 = 5
|
||||
* - z = 1111 = 15
|
||||
* => Chunklet coordinates (5, 15)
|
||||
*/
|
||||
protected static byte makeAddressByte(int x, int z) {
|
||||
return (byte) ((x << 4) + z);
|
||||
}
|
||||
|
||||
protected static int addressByteX(byte address) {
|
||||
return (address & 0xF0) >>> 4;
|
||||
}
|
||||
|
||||
protected static int addressByteZ(byte address) {
|
||||
return address & 0x0F;
|
||||
}
|
||||
}
|
@ -1,177 +0,0 @@
|
||||
package com.gmail.nossr50.util.blockmeta.chunkmeta;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
public interface ChunkManager {
|
||||
public void closeAll();
|
||||
public ChunkStore readChunkStore(World world, int x, int z) throws IOException;
|
||||
public void writeChunkStore(World world, int x, int z, ChunkStore data);
|
||||
public void closeChunkStore(World world, int x, int z);
|
||||
|
||||
/**
|
||||
* Loads a specific chunklet
|
||||
*
|
||||
* @param cx Chunklet X coordinate that needs to be loaded
|
||||
* @param cy Chunklet Y coordinate that needs to be loaded
|
||||
* @param cz Chunklet Z coordinate that needs to be loaded
|
||||
* @param world World that the chunklet needs to be loaded in
|
||||
*/
|
||||
public void loadChunklet(int cx, int cy, int cz, World world);
|
||||
|
||||
/**
|
||||
* Unload a specific chunklet
|
||||
*
|
||||
* @param cx Chunklet X coordinate that needs to be unloaded
|
||||
* @param cy Chunklet Y coordinate that needs to be unloaded
|
||||
* @param cz Chunklet Z coordinate that needs to be unloaded
|
||||
* @param world World that the chunklet needs to be unloaded from
|
||||
*/
|
||||
public void unloadChunklet(int cx, int cy, int cz, World world);
|
||||
|
||||
/**
|
||||
* Load a given Chunk's Chunklet data
|
||||
*
|
||||
* @param cx Chunk X coordinate that is to be loaded
|
||||
* @param cz Chunk Z coordinate that is to be loaded
|
||||
* @param world World that the Chunk is in
|
||||
*/
|
||||
public void loadChunk(int cx, int cz, World world, Entity[] entities);
|
||||
|
||||
/**
|
||||
* Unload a given Chunk's Chunklet data
|
||||
*
|
||||
* @param cx Chunk X coordinate that is to be unloaded
|
||||
* @param cz Chunk Z coordinate that is to be unloaded
|
||||
* @param world World that the Chunk is in
|
||||
*/
|
||||
public void unloadChunk(int cx, int cz, World world);
|
||||
|
||||
/**
|
||||
* Saves a given Chunk's Chunklet data
|
||||
*
|
||||
* @param cx Chunk X coordinate that is to be saved
|
||||
* @param cz Chunk Z coordinate that is to be saved
|
||||
* @param world World that the Chunk is in
|
||||
*/
|
||||
public void saveChunk(int cx, int cz, World world);
|
||||
|
||||
public boolean isChunkLoaded(int cx, int cz, World world);
|
||||
/**
|
||||
* Informs the ChunkletManager a chunk is loaded
|
||||
*
|
||||
* @param cx Chunk X coordinate that is loaded
|
||||
* @param cz Chunk Z coordinate that is loaded
|
||||
* @param world World that the chunk was loaded in
|
||||
*/
|
||||
public void chunkLoaded(int cx, int cz, World world);
|
||||
|
||||
/**
|
||||
* Informs the ChunkletManager a chunk is unloaded
|
||||
*
|
||||
* @param cx Chunk X coordinate that is unloaded
|
||||
* @param cz Chunk Z coordinate that is unloaded
|
||||
* @param world World that the chunk was unloaded in
|
||||
*/
|
||||
public void chunkUnloaded(int cx, int cz, World world);
|
||||
|
||||
/**
|
||||
* Save all ChunkletStores related to the given world
|
||||
*
|
||||
* @param world World to save
|
||||
*/
|
||||
public void saveWorld(World world);
|
||||
|
||||
/**
|
||||
* Unload all ChunkletStores from memory related to the given world after saving them
|
||||
*
|
||||
* @param world World to unload
|
||||
*/
|
||||
public void unloadWorld(World world);
|
||||
|
||||
/**
|
||||
* Load all ChunkletStores from all loaded chunks from this world into memory
|
||||
*
|
||||
* @param world World to load
|
||||
*/
|
||||
public void loadWorld(World world);
|
||||
|
||||
/**
|
||||
* Save all ChunkletStores
|
||||
*/
|
||||
public void saveAll();
|
||||
|
||||
/**
|
||||
* Unload all ChunkletStores after saving them
|
||||
*/
|
||||
public void unloadAll();
|
||||
|
||||
/**
|
||||
* Check to see if a given location is set to true
|
||||
*
|
||||
* @param x X coordinate to check
|
||||
* @param y Y coordinate to check
|
||||
* @param z Z coordinate to check
|
||||
* @param world World to check in
|
||||
* @return true if the given location is set to true, false if otherwise
|
||||
*/
|
||||
public boolean isTrue(int x, int y, int z, World world);
|
||||
|
||||
/**
|
||||
* Check to see if a given block location is set to true
|
||||
*
|
||||
* @param block Block location to check
|
||||
* @return true if the given block location is set to true, false if otherwise
|
||||
*/
|
||||
public boolean isTrue(Block block);
|
||||
|
||||
/**
|
||||
* Set a given location to true, should create stores as necessary if the location does not exist
|
||||
*
|
||||
* @param x X coordinate to set
|
||||
* @param y Y coordinate to set
|
||||
* @param z Z coordinate to set
|
||||
* @param world World to set in
|
||||
*/
|
||||
public void setTrue(int x, int y, int z, World world);
|
||||
|
||||
/**
|
||||
* Set a given block location to true, should create stores as necessary if the location does not exist
|
||||
*
|
||||
* @param block Block location to set
|
||||
*/
|
||||
public void setTrue(Block block);
|
||||
|
||||
/**
|
||||
* Set a given location to false, should not create stores if one does not exist for the given location
|
||||
*
|
||||
* @param x X coordinate to set
|
||||
* @param y Y coordinate to set
|
||||
* @param z Z coordinate to set
|
||||
* @param world World to set in
|
||||
*/
|
||||
public void setFalse(int x, int y, int z, World world);
|
||||
|
||||
/**
|
||||
* Set a given block location to false, should not create stores if one does not exist for the given location
|
||||
*
|
||||
* @param block Block location to set
|
||||
*/
|
||||
public void setFalse(Block block);
|
||||
|
||||
/**
|
||||
* Delete any ChunkletStores that are empty
|
||||
*/
|
||||
public void cleanUp();
|
||||
|
||||
public boolean isSpawnedMob(Entity entity);
|
||||
public boolean isSpawnedPet(Entity entity);
|
||||
public void addSpawnedMob(Entity entity);
|
||||
public void addSpawnedPet(Entity entity);
|
||||
public void removeSpawnedMob(Entity entity);
|
||||
public void removeSpawnedPet(Entity entity);
|
||||
public void cleanMobLists();
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
package com.gmail.nossr50.util.blockmeta.chunkmeta;
|
||||
|
||||
import com.gmail.nossr50.config.HiddenConfig;
|
||||
|
||||
public class ChunkManagerFactory {
|
||||
public static ChunkManager getChunkManager() {
|
||||
HiddenConfig hConfig = HiddenConfig.getInstance();
|
||||
|
||||
if (hConfig.getChunkletsEnabled()) {
|
||||
return new HashChunkManager();
|
||||
}
|
||||
|
||||
return new NullChunkManager();
|
||||
}
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
package com.gmail.nossr50.util.blockmeta.chunkmeta;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.gmail.nossr50.util.blockmeta.ChunkletStore;
|
||||
|
||||
/**
|
||||
* A ChunkStore should be responsible for a 16x16xWorldHeight area of data
|
||||
*/
|
||||
public interface ChunkStore extends Serializable {
|
||||
/**
|
||||
* Checks the chunk's save state
|
||||
*
|
||||
* @return true if the has been modified since it was last saved
|
||||
*/
|
||||
public boolean isDirty();
|
||||
/**
|
||||
* Checks the chunk's save state
|
||||
*
|
||||
* @param dirty the save state of the current chunk
|
||||
*/
|
||||
public void setDirty(boolean dirty);
|
||||
/**
|
||||
* Checks the chunk's x coordinate
|
||||
*
|
||||
* @return the chunk's x coordinate.
|
||||
*/
|
||||
public int getChunkX();
|
||||
/**
|
||||
* Checks the chunk's z coordinate
|
||||
*
|
||||
* @return the chunk's z coordinate.
|
||||
*/
|
||||
public int getChunkZ();
|
||||
/**
|
||||
* Checks the value at the given coordinates
|
||||
*
|
||||
* @param x x coordinate in current chunklet
|
||||
* @param y y coordinate in current chunklet
|
||||
* @param z z coordinate in current chunklet
|
||||
* @return true if the value is true at the given coordinates, false if otherwise
|
||||
*/
|
||||
public boolean isTrue(int x, int y, int z);
|
||||
|
||||
/**
|
||||
* Set the value to true at the given coordinates
|
||||
*
|
||||
* @param x x coordinate in current chunklet
|
||||
* @param y y coordinate in current chunklet
|
||||
* @param z z coordinate in current chunklet
|
||||
*/
|
||||
public void setTrue(int x, int y, int z);
|
||||
|
||||
/**
|
||||
* Set the value to false at the given coordinates
|
||||
*
|
||||
* @param x x coordinate in current chunklet
|
||||
* @param y y coordinate in current chunklet
|
||||
* @param z z coordinate in current chunklet
|
||||
*/
|
||||
public void setFalse(int x, int y, int z);
|
||||
|
||||
/**
|
||||
* @return true if all values in the chunklet are false, false if otherwise
|
||||
*/
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Set all values in this ChunkletStore to the values from another provided ChunkletStore
|
||||
*
|
||||
* @param otherStore Another ChunkletStore that this one should copy all data from
|
||||
*/
|
||||
public void copyFrom(ChunkletStore otherStore);
|
||||
|
||||
public boolean isSpawnedMob(UUID id);
|
||||
public boolean isSpawnedPet(UUID id);
|
||||
public void addSpawnedMob(UUID id);
|
||||
public void addSpawnedPet(UUID id);
|
||||
public void removeSpawnedMob(UUID id);
|
||||
public void removeSpawnedPet(UUID id);
|
||||
public void clearSpawnedMobs();
|
||||
public void clearSpawnedPets();
|
||||
public List<UUID> getSpawnedMobs();
|
||||
public List<UUID> getSpawnedPets();
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package com.gmail.nossr50.util.blockmeta.chunkmeta;
|
||||
|
||||
import org.bukkit.World;
|
||||
|
||||
public class ChunkStoreFactory {
|
||||
protected static ChunkStore getChunkStore(World world, int x, int z) {
|
||||
// TODO: Add in loading from config what type of store we want.
|
||||
return new PrimitiveChunkStore(world, x, z);
|
||||
}
|
||||
}
|
@ -1,630 +0,0 @@
|
||||
package com.gmail.nossr50.util.blockmeta.chunkmeta;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.getspout.spoutapi.chunkstore.mcMMOSimpleRegionFile;
|
||||
|
||||
import com.gmail.nossr50.runnables.blockstoreconversion.BlockStoreConversionZDirectory;
|
||||
|
||||
public class HashChunkManager implements ChunkManager {
|
||||
private HashMap<UUID, HashMap<Long, mcMMOSimpleRegionFile>> regionFiles = new HashMap<UUID, HashMap<Long, mcMMOSimpleRegionFile>>();
|
||||
public HashMap<String, ChunkStore> store = new HashMap<String, ChunkStore>();
|
||||
public ArrayList<BlockStoreConversionZDirectory> converters = new ArrayList<BlockStoreConversionZDirectory>();
|
||||
private HashMap<UUID, Boolean> oldData = new HashMap<UUID, Boolean>();
|
||||
// TODO: Investigate whether or not a LinkedList would be faster
|
||||
private List<Entity> spawnedMobs = new ArrayList<Entity>();
|
||||
private List<Entity> mobsToRemove = new ArrayList<Entity>();
|
||||
private List<String> savedChunks = new ArrayList<String>();
|
||||
private List<Entity> checkedMobs = new ArrayList<Entity>();
|
||||
private List<Entity> removalCheckedMobs = new ArrayList<Entity>();
|
||||
private boolean safeToRemoveMobs = true;
|
||||
private boolean savingWorld = false;
|
||||
private boolean iteratingMobs = false;
|
||||
|
||||
@Override
|
||||
public synchronized void closeAll() {
|
||||
for (UUID uid : regionFiles.keySet()) {
|
||||
HashMap<Long, mcMMOSimpleRegionFile> worldRegions = regionFiles.get(uid);
|
||||
for (Iterator<mcMMOSimpleRegionFile> worldRegionIterator = worldRegions.values().iterator(); worldRegionIterator.hasNext();) {
|
||||
mcMMOSimpleRegionFile rf = worldRegionIterator.next();
|
||||
if (rf != null) {
|
||||
rf.close();
|
||||
worldRegionIterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
regionFiles.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized ChunkStore readChunkStore(World world, int x, int z) throws IOException {
|
||||
mcMMOSimpleRegionFile rf = getSimpleRegionFile(world, x, z);
|
||||
InputStream in = rf.getInputStream(x, z);
|
||||
if (in == null) {
|
||||
return null;
|
||||
}
|
||||
ObjectInputStream objectStream = new ObjectInputStream(in);
|
||||
try {
|
||||
Object o = objectStream.readObject();
|
||||
if (o instanceof ChunkStore) {
|
||||
return (ChunkStore) o;
|
||||
}
|
||||
|
||||
throw new RuntimeException("Wrong class type read for chunk meta data for " + x + ", " + z);
|
||||
} catch (IOException e) {
|
||||
// Assume the format changed
|
||||
return null;
|
||||
//throw new RuntimeException("Unable to process chunk meta data for " + x + ", " + z, e);
|
||||
} catch (ClassNotFoundException e) {
|
||||
// Assume the format changed
|
||||
//System.out.println("[SpoutPlugin] is Unable to find serialized class for " + x + ", " + z + ", " + e.getMessage());
|
||||
return null;
|
||||
//throw new RuntimeException("Unable to find serialized class for " + x + ", " + z, e);
|
||||
}
|
||||
finally {
|
||||
objectStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void writeChunkStore(World world, int x, int z, ChunkStore data) {
|
||||
if (!data.isDirty()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mcMMOSimpleRegionFile rf = getSimpleRegionFile(world, x, z);
|
||||
ObjectOutputStream objectStream = new ObjectOutputStream(rf.getOutputStream(x, z));
|
||||
objectStream.writeObject(data);
|
||||
objectStream.flush();
|
||||
objectStream.close();
|
||||
data.setDirty(false);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Unable to write chunk meta data for " + x + ", " + z, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void closeChunkStore(World world, int x, int z) {
|
||||
mcMMOSimpleRegionFile rf = getSimpleRegionFile(world, x, z);
|
||||
if (rf != null) {
|
||||
rf.close();
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized mcMMOSimpleRegionFile getSimpleRegionFile(World world, int x, int z) {
|
||||
File directory = new File(world.getWorldFolder(), "mcmmo_regions");
|
||||
|
||||
directory.mkdirs();
|
||||
|
||||
UUID key = world.getUID();
|
||||
|
||||
HashMap<Long, mcMMOSimpleRegionFile> worldRegions = regionFiles.get(key);
|
||||
|
||||
if (worldRegions == null) {
|
||||
worldRegions = new HashMap<Long, mcMMOSimpleRegionFile>();
|
||||
regionFiles.put(key, worldRegions);
|
||||
}
|
||||
|
||||
int rx = x >> 5;
|
||||
int rz = z >> 5;
|
||||
|
||||
long key2 = (((long) rx) << 32) | ((rz) & 0xFFFFFFFFL);
|
||||
|
||||
mcMMOSimpleRegionFile regionFile = worldRegions.get(key2);
|
||||
|
||||
if (regionFile == null) {
|
||||
File file = new File(directory, "mcmmo_" + rx + "_" + rz + "_.mcm");
|
||||
regionFile = new mcMMOSimpleRegionFile(file, rx, rz);
|
||||
worldRegions.put(key2, regionFile);
|
||||
}
|
||||
|
||||
return regionFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void loadChunklet(int cx, int cy, int cz, World world) {
|
||||
loadChunk(cx, cz, world, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void unloadChunklet(int cx, int cy, int cz, World world) {
|
||||
unloadChunk(cx, cz, world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void loadChunk(int cx, int cz, World world, Entity[] entities) {
|
||||
if (world == null || store.containsKey(world.getName() + "," + cx + "," + cz))
|
||||
return;
|
||||
|
||||
UUID key = world.getUID();
|
||||
|
||||
if (!oldData.containsKey(key)) {
|
||||
oldData.put(key, (new File(world.getWorldFolder(), "mcmmo_data")).exists());
|
||||
}
|
||||
else if (oldData.get(key)) {
|
||||
if (convertChunk(new File(world.getWorldFolder(), "mcmmo_data"), cx, cz, world, true))
|
||||
return;
|
||||
}
|
||||
|
||||
ChunkStore chunkStore = null;
|
||||
|
||||
try {
|
||||
chunkStore = readChunkStore(world, cx, cz);
|
||||
}
|
||||
catch (Exception e) {}
|
||||
|
||||
if (chunkStore == null)
|
||||
return;
|
||||
|
||||
store.put(world.getName() + "," + cx + "," + cz, chunkStore);
|
||||
|
||||
List<UUID> mobs = chunkStore.getSpawnedMobs();
|
||||
|
||||
if (mobs.isEmpty())
|
||||
return;
|
||||
|
||||
if (entities == null)
|
||||
entities = world.getChunkAt(cx, cz).getEntities();
|
||||
|
||||
iteratingMobs = true;
|
||||
|
||||
for (Entity entity : entities) {
|
||||
if (mobs.contains(entity.getUniqueId()))
|
||||
addSpawnedMob(entity);
|
||||
}
|
||||
|
||||
if (safeToRemoveMobs)
|
||||
iteratingMobs = false;
|
||||
|
||||
chunkStore.clearSpawnedMobs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void unloadChunk(int cx, int cz, World world) {
|
||||
saveChunk(cx, cz, world);
|
||||
|
||||
if (store.containsKey(world.getName() + "," + cx + "," + cz)) {
|
||||
store.remove(world.getName() + "," + cx + "," + cz);
|
||||
|
||||
iteratingMobs = true;
|
||||
|
||||
List<Entity> tempSpawnedMobs = new ArrayList<Entity>(spawnedMobs);
|
||||
tempSpawnedMobs.removeAll(removalCheckedMobs);
|
||||
tempSpawnedMobs.removeAll(checkedMobs);
|
||||
for (Entity entity : tempSpawnedMobs) {
|
||||
if (!isEntityInChunk(entity, cx, cz, world))
|
||||
continue;
|
||||
|
||||
mobsToRemove.add(entity);
|
||||
removalCheckedMobs.add(entity);
|
||||
}
|
||||
|
||||
if (safeToRemoveMobs) {
|
||||
spawnedMobs.removeAll(mobsToRemove);
|
||||
mobsToRemove.clear();
|
||||
removalCheckedMobs.clear();
|
||||
iteratingMobs = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void saveChunk(int cx, int cz, World world) {
|
||||
if (world == null)
|
||||
return;
|
||||
|
||||
if (savingWorld && savedChunks.contains(world.getName() + "," + cx + "," + cz))
|
||||
return;
|
||||
|
||||
boolean unloaded = false;
|
||||
String key = world.getName() + "," + cx + "," + cz;
|
||||
|
||||
if (!store.containsKey(key)) {
|
||||
List<Entity> tempSpawnedMobs = new ArrayList<Entity>(spawnedMobs);
|
||||
tempSpawnedMobs.removeAll(checkedMobs);
|
||||
for (Entity entity : tempSpawnedMobs) {
|
||||
if (!isEntityInChunk(entity, cx, cz, world))
|
||||
continue;
|
||||
|
||||
loadChunk(cx, cz, world, null);
|
||||
unloaded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!store.containsKey(key) && unloaded) {
|
||||
ChunkStore cStore = ChunkStoreFactory.getChunkStore(world, cx, cz);
|
||||
store.put(world.getName() + "," + cx + "," + cz, cStore);
|
||||
}
|
||||
|
||||
if (store.containsKey(key)) {
|
||||
ChunkStore out = store.get(world.getName() + "," + cx + "," + cz);
|
||||
|
||||
List<Entity> tempSpawnedMobs = new ArrayList<Entity>(spawnedMobs);
|
||||
tempSpawnedMobs.removeAll(checkedMobs);
|
||||
for (Entity entity : tempSpawnedMobs) {
|
||||
if (!isEntityInChunk(entity, cx, cz, world))
|
||||
continue;
|
||||
|
||||
out.addSpawnedMob(entity.getUniqueId());
|
||||
checkedMobs.add(entity);
|
||||
}
|
||||
|
||||
if (!out.isDirty())
|
||||
return;
|
||||
|
||||
writeChunkStore(world, cx, cz, out);
|
||||
}
|
||||
|
||||
if(savingWorld)
|
||||
savedChunks.add(world.getName() + "," + cx + "," + cz);
|
||||
else
|
||||
checkedMobs.clear();
|
||||
}
|
||||
|
||||
private boolean isEntityInChunk(Entity entity, int cx, int cz, World world) {
|
||||
if (entity == null || world == null)
|
||||
return false;
|
||||
|
||||
Chunk chunk = entity.getLocation().getChunk();
|
||||
|
||||
if (chunk.getX() != cx)
|
||||
return false;
|
||||
|
||||
if (chunk.getZ() != cz)
|
||||
return false;
|
||||
|
||||
if (entity.getWorld() != world)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean isChunkLoaded(int cx, int cz, World world) {
|
||||
if (world == null)
|
||||
return false;
|
||||
|
||||
return store.containsKey(world.getName() + "," + cx + "," + cz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void chunkLoaded(int cx, int cz, World world) {}
|
||||
|
||||
@Override
|
||||
public synchronized void chunkUnloaded(int cx, int cz, World world) {
|
||||
if (world == null)
|
||||
return;
|
||||
|
||||
unloadChunk(cx, cz, world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void saveWorld(World world) {
|
||||
if (world == null)
|
||||
return;
|
||||
|
||||
closeAll();
|
||||
String worldName = world.getName();
|
||||
savingWorld = true;
|
||||
|
||||
List<String> keys = new ArrayList<String>(store.keySet());
|
||||
for (String key : keys) {
|
||||
String[] info = key.split(",");
|
||||
if (worldName.equals(info[0])) {
|
||||
int cx = 0;
|
||||
int cz = 0;
|
||||
|
||||
try {
|
||||
cx = Integer.parseInt(info[1]);
|
||||
cz = Integer.parseInt(info[2]);
|
||||
}
|
||||
catch(Exception e) {
|
||||
continue;
|
||||
}
|
||||
saveChunk(cx, cz, world);
|
||||
}
|
||||
}
|
||||
|
||||
List<Entity> tempSpawnedMobs = new ArrayList<Entity>(spawnedMobs);
|
||||
tempSpawnedMobs.removeAll(checkedMobs);
|
||||
for (Entity entity : tempSpawnedMobs) {
|
||||
World entityWorld = entity.getWorld();
|
||||
|
||||
if (world != entityWorld)
|
||||
continue;
|
||||
|
||||
int cx = entity.getLocation().getChunk().getX();
|
||||
int cz = entity.getLocation().getChunk().getZ();
|
||||
|
||||
saveChunk(cx, cz, world);
|
||||
}
|
||||
|
||||
savingWorld = false;
|
||||
savedChunks.clear();
|
||||
checkedMobs.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void unloadWorld(World world) {
|
||||
if (world == null)
|
||||
return;
|
||||
|
||||
closeAll();
|
||||
String worldName = world.getName();
|
||||
savingWorld = true;
|
||||
|
||||
List<String> keys = new ArrayList<String>(store.keySet());
|
||||
for (String key : keys) {
|
||||
String[] info = key.split(",");
|
||||
if (worldName.equals(info[0])) {
|
||||
int cx = 0;
|
||||
int cz = 0;
|
||||
|
||||
try {
|
||||
cx = Integer.parseInt(info[1]);
|
||||
cz = Integer.parseInt(info[2]);
|
||||
}
|
||||
catch(Exception e) {
|
||||
continue;
|
||||
}
|
||||
unloadChunk(cx, cz, world);
|
||||
}
|
||||
}
|
||||
|
||||
safeToRemoveMobs = false;
|
||||
|
||||
List<Entity> tempSpawnedMobs = new ArrayList<Entity>(spawnedMobs);
|
||||
tempSpawnedMobs.removeAll(checkedMobs);
|
||||
tempSpawnedMobs.removeAll(removalCheckedMobs);
|
||||
for (Entity entity : tempSpawnedMobs) {
|
||||
World entityWorld = entity.getWorld();
|
||||
|
||||
if (world != entityWorld)
|
||||
continue;
|
||||
|
||||
int cx = entity.getLocation().getChunk().getX();
|
||||
int cz = entity.getLocation().getChunk().getZ();
|
||||
|
||||
unloadChunk(cx, cz, world);
|
||||
}
|
||||
|
||||
safeToRemoveMobs = true;
|
||||
|
||||
spawnedMobs.removeAll(mobsToRemove);
|
||||
mobsToRemove.clear();
|
||||
checkedMobs.clear();
|
||||
removalCheckedMobs.clear();
|
||||
savingWorld = false;
|
||||
savedChunks.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void loadWorld(World world) {}
|
||||
|
||||
@Override
|
||||
public synchronized void saveAll() {
|
||||
closeAll();
|
||||
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
saveWorld(world);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void unloadAll() {
|
||||
closeAll();
|
||||
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
unloadWorld(world);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean isTrue(int x, int y, int z, World world) {
|
||||
if (world == null)
|
||||
return false;
|
||||
|
||||
int cx = x / 16;
|
||||
int cz = z / 16;
|
||||
String key = world.getName() + "," + cx + "," + cz;
|
||||
|
||||
if (!store.containsKey(key)) {
|
||||
loadChunk(cx, cz, world, null);
|
||||
}
|
||||
|
||||
if (!store.containsKey(key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ChunkStore check = store.get(key);
|
||||
int ix = Math.abs(x) % 16;
|
||||
int iz = Math.abs(z) % 16;
|
||||
|
||||
return check.isTrue(ix, y, iz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean isTrue(Block block) {
|
||||
if (block == null)
|
||||
return false;
|
||||
|
||||
return isTrue(block.getX(), block.getY(), block.getZ(), block.getWorld());
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setTrue(int x, int y, int z, World world) {
|
||||
if (world == null)
|
||||
return;
|
||||
|
||||
int cx = x / 16;
|
||||
int cz = z / 16;
|
||||
|
||||
int ix = Math.abs(x) % 16;
|
||||
int iz = Math.abs(z) % 16;
|
||||
|
||||
String key = world.getName() + "," + cx + "," + cz;
|
||||
|
||||
if (!store.containsKey(key)) {
|
||||
loadChunk(cx, cz, world, null);
|
||||
}
|
||||
|
||||
ChunkStore cStore = store.get(key);
|
||||
|
||||
if (cStore == null) {
|
||||
cStore = ChunkStoreFactory.getChunkStore(world, cx, cz);
|
||||
store.put(key, cStore);
|
||||
}
|
||||
|
||||
cStore.setTrue(ix, y, iz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setTrue(Block block) {
|
||||
if (block == null)
|
||||
return;
|
||||
|
||||
setTrue(block.getX(), block.getY(), block.getZ(), block.getWorld());
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setFalse(int x, int y, int z, World world) {
|
||||
if (world == null)
|
||||
return;
|
||||
|
||||
int cx = x / 16;
|
||||
int cz = z / 16;
|
||||
|
||||
int ix = Math.abs(x) % 16;
|
||||
int iz = Math.abs(z) % 16;
|
||||
|
||||
String key = world.getName() + "," + cx + "," + cz;
|
||||
|
||||
if (!store.containsKey(key)) {
|
||||
loadChunk(cx, cz, world, null);
|
||||
}
|
||||
|
||||
ChunkStore cStore = store.get(key);
|
||||
|
||||
if (cStore == null) {
|
||||
return; //No need to make a store for something we will be setting to false
|
||||
}
|
||||
|
||||
cStore.setFalse(ix, y, iz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setFalse(Block block) {
|
||||
if (block == null)
|
||||
return;
|
||||
|
||||
setFalse(block.getX(), block.getY(), block.getZ(), block.getWorld());
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void cleanUp() {}
|
||||
|
||||
public synchronized void convertChunk(File dataDir, int cx, int cz, World world) {
|
||||
convertChunk(dataDir, cx, cz, world, false);
|
||||
}
|
||||
|
||||
public synchronized boolean convertChunk(File dataDir, int cx, int cz, World world, boolean actually) {
|
||||
if (!actually)
|
||||
return false;
|
||||
if (!dataDir.exists()) return false;
|
||||
File cxDir = new File(dataDir, "" + cx);
|
||||
if (!cxDir.exists()) return false;
|
||||
File czDir = new File(cxDir, "" + cz);
|
||||
if (!czDir.exists()) return false;
|
||||
|
||||
boolean conversionSet = false;
|
||||
|
||||
for (BlockStoreConversionZDirectory converter : this.converters) {
|
||||
if (converter == null)
|
||||
continue;
|
||||
|
||||
if (converter.taskID >= 0)
|
||||
continue;
|
||||
|
||||
converter.start(world, cxDir, czDir);
|
||||
conversionSet = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!conversionSet) {
|
||||
BlockStoreConversionZDirectory converter = new BlockStoreConversionZDirectory();
|
||||
converter.start(world, cxDir, czDir);
|
||||
converters.add(converter);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSpawnedMob(Entity entity) {
|
||||
return spawnedMobs.contains(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSpawnedPet(Entity entity) {
|
||||
return spawnedMobs.contains(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSpawnedMob(Entity entity) {
|
||||
if (!isSpawnedMob(entity))
|
||||
spawnedMobs.add(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSpawnedPet(Entity entity) {
|
||||
if (!isSpawnedMob(entity))
|
||||
spawnedMobs.add(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSpawnedMob(Entity entity) {
|
||||
if (isSpawnedMob(entity))
|
||||
spawnedMobs.remove(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSpawnedPet(Entity entity) {
|
||||
if (isSpawnedMob(entity))
|
||||
spawnedMobs.remove(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void cleanMobLists() {
|
||||
if (!safeToRemoveMobs || iteratingMobs)
|
||||
return;
|
||||
|
||||
mobsToRemove.clear();
|
||||
|
||||
List<Entity> tempSpawnedMobs = new ArrayList<Entity>(spawnedMobs);
|
||||
for (Entity entity : tempSpawnedMobs) {
|
||||
if (entity.isDead())
|
||||
mobsToRemove.add(entity);
|
||||
|
||||
if (!entity.isValid())
|
||||
mobsToRemove.add(entity);
|
||||
}
|
||||
|
||||
spawnedMobs.removeAll(mobsToRemove);
|
||||
mobsToRemove.clear();
|
||||
}
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
package com.gmail.nossr50.util.blockmeta.chunkmeta;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
public class NullChunkManager implements ChunkManager {
|
||||
|
||||
@Override
|
||||
public void closeAll() {}
|
||||
|
||||
@Override
|
||||
public ChunkStore readChunkStore(World world, int x, int z) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeChunkStore(World world, int x, int z, ChunkStore data) {}
|
||||
|
||||
@Override
|
||||
public void closeChunkStore(World world, int x, int z) {}
|
||||
|
||||
@Override
|
||||
public void loadChunklet(int cx, int cy, int cz, World world) {}
|
||||
|
||||
@Override
|
||||
public void unloadChunklet(int cx, int cy, int cz, World world) {}
|
||||
|
||||
@Override
|
||||
public void loadChunk(int cx, int cz, World world, Entity[] entities) {}
|
||||
|
||||
@Override
|
||||
public void unloadChunk(int cx, int cz, World world) {}
|
||||
|
||||
@Override
|
||||
public void saveChunk(int cx, int cz, World world) {}
|
||||
|
||||
@Override
|
||||
public boolean isChunkLoaded(int cx, int cz, World world) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void chunkLoaded(int cx, int cz, World world) {}
|
||||
|
||||
@Override
|
||||
public void chunkUnloaded(int cx, int cz, World world) {}
|
||||
|
||||
@Override
|
||||
public void saveWorld(World world) {}
|
||||
|
||||
@Override
|
||||
public void unloadWorld(World world) {}
|
||||
|
||||
@Override
|
||||
public void loadWorld(World world) {}
|
||||
|
||||
@Override
|
||||
public void saveAll() {}
|
||||
|
||||
@Override
|
||||
public void unloadAll() {}
|
||||
|
||||
@Override
|
||||
public boolean isTrue(int x, int y, int z, World world) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTrue(Block block) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTrue(int x, int y, int z, World world) {}
|
||||
|
||||
@Override
|
||||
public void setTrue(Block block) {}
|
||||
|
||||
@Override
|
||||
public void setFalse(int x, int y, int z, World world) {}
|
||||
|
||||
@Override
|
||||
public void setFalse(Block block) {}
|
||||
|
||||
@Override
|
||||
public void cleanUp() {}
|
||||
|
||||
@Override
|
||||
public boolean isSpawnedMob(Entity entity) {return false;}
|
||||
@Override
|
||||
public boolean isSpawnedPet(Entity entity) {return false;}
|
||||
@Override
|
||||
public void addSpawnedMob(Entity entity) {}
|
||||
@Override
|
||||
public void addSpawnedPet(Entity entity) {}
|
||||
@Override
|
||||
public void removeSpawnedMob(Entity entity) {}
|
||||
@Override
|
||||
public void removeSpawnedPet(Entity entity) {}
|
||||
@Override
|
||||
public synchronized void cleanMobLists() {}
|
||||
}
|
@ -1,250 +0,0 @@
|
||||
package com.gmail.nossr50.util.blockmeta.chunkmeta;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.World;
|
||||
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import com.gmail.nossr50.util.blockmeta.ChunkletStore;
|
||||
|
||||
public class PrimitiveChunkStore implements ChunkStore {
|
||||
private static final long serialVersionUID = -1L;
|
||||
transient private boolean dirty = false;
|
||||
/** X, Z, Y */
|
||||
public boolean[][][] store;
|
||||
private static final int CURRENT_VERSION = 7;
|
||||
private static final int MAGIC_NUMBER = 0xEA5EDEBB;
|
||||
private int cx;
|
||||
private int cz;
|
||||
private UUID worldUid;
|
||||
private List<UUID> spawnedMobs = new ArrayList<UUID>();
|
||||
transient private int worldHeight;
|
||||
|
||||
transient private int xBitShifts;
|
||||
transient private int zBitShifts;
|
||||
transient private boolean conversionNeeded;
|
||||
|
||||
public PrimitiveChunkStore(World world, int cx, int cz) {
|
||||
this.cx = cx;
|
||||
this.cz = cz;
|
||||
this.worldUid = world.getUID();
|
||||
|
||||
this.worldHeight = world != null ? world.getMaxHeight() : 128;
|
||||
this.xBitShifts = 11;
|
||||
this.zBitShifts = 7;
|
||||
|
||||
this.store = new boolean[16][16][this.worldHeight];
|
||||
|
||||
conversionNeeded = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirty() {
|
||||
return dirty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDirty(boolean dirty) {
|
||||
this.dirty = dirty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChunkX() {
|
||||
return cx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChunkZ() {
|
||||
return cz;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTrue(int x, int y, int z) {
|
||||
return store[x][z][y];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTrue(int x, int y, int z) {
|
||||
store[x][z][y] = true;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFalse(int x, int y, int z) {
|
||||
store[x][z][y] = false;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int y = 0; y < this.worldHeight; y++) {
|
||||
if (store[x][z][y]) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyFrom(ChunkletStore otherStore) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int y = 0; y < this.worldHeight; y++) {
|
||||
store[x][z][y] = otherStore.isTrue(x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSpawnedMob(UUID id) {
|
||||
return spawnedMobs.contains(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSpawnedPet(UUID id) {
|
||||
return spawnedMobs.contains(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSpawnedMob(UUID id) {
|
||||
if (!isSpawnedMob(id)) {
|
||||
spawnedMobs.add(id);
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSpawnedPet(UUID id) {
|
||||
if (!isSpawnedPet(id)) {
|
||||
spawnedMobs.add(id);
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSpawnedMob(UUID id) {
|
||||
if (isSpawnedMob(id)) {
|
||||
spawnedMobs.remove(id);
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSpawnedPet(UUID id) {
|
||||
if (isSpawnedPet(id)) {
|
||||
spawnedMobs.remove(id);
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearSpawnedMobs() {
|
||||
if (!spawnedMobs.isEmpty()) {
|
||||
spawnedMobs.clear();
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearSpawnedPets() {
|
||||
if (!spawnedMobs.isEmpty()) {
|
||||
spawnedMobs.clear();
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UUID> getSpawnedMobs() {
|
||||
return spawnedMobs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UUID> getSpawnedPets() {
|
||||
return spawnedMobs;
|
||||
}
|
||||
|
||||
private void writeObject(ObjectOutputStream out) throws IOException {
|
||||
out.writeInt(MAGIC_NUMBER);
|
||||
out.writeInt(CURRENT_VERSION);
|
||||
|
||||
out.writeLong(worldUid.getLeastSignificantBits());
|
||||
out.writeLong(worldUid.getMostSignificantBits());
|
||||
out.writeInt(cx);
|
||||
out.writeInt(cz);
|
||||
out.writeObject(store);
|
||||
|
||||
out.writeObject(spawnedMobs);
|
||||
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
int fileVersionNumber; // Can be used to determine the format of the file
|
||||
|
||||
long lsb = in.readLong();
|
||||
if (((int) (lsb >> 32)) == MAGIC_NUMBER) {
|
||||
fileVersionNumber = (int) lsb;
|
||||
lsb = in.readLong();
|
||||
} else {
|
||||
fileVersionNumber = 0;
|
||||
}
|
||||
|
||||
long msb = in.readLong();
|
||||
worldUid = new UUID(msb, lsb);
|
||||
cx = in.readInt();
|
||||
cz = in.readInt();
|
||||
|
||||
// Constructor is not invoked, need to set these fields
|
||||
World world = mcMMO.p.getServer().getWorld(this.worldUid);
|
||||
|
||||
this.worldHeight = world.getMaxHeight();
|
||||
this.xBitShifts = 11;
|
||||
this.zBitShifts = 7;
|
||||
|
||||
store = (boolean[][][]) in.readObject();
|
||||
|
||||
if (fileVersionNumber < CURRENT_VERSION) {
|
||||
if (fileVersionNumber < 5)
|
||||
fixArray();
|
||||
if (fileVersionNumber < 6) {
|
||||
spawnedMobs = new ArrayList<UUID>();
|
||||
}
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
if (fileVersionNumber == 6) {
|
||||
//What do we want to do about this? These casts are unchecked.
|
||||
spawnedMobs = (ArrayList<UUID>) in.readObject();
|
||||
List<UUID> spawnedPets = (ArrayList<UUID>) in.readObject();
|
||||
spawnedMobs.addAll(spawnedPets);
|
||||
}
|
||||
|
||||
if(fileVersionNumber >= 7) {
|
||||
spawnedMobs = (ArrayList<UUID>) in.readObject();
|
||||
}
|
||||
}
|
||||
|
||||
private void fixArray() {
|
||||
boolean[][][] temp = this.store;
|
||||
this.store = new boolean[16][16][this.worldHeight];
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int y = 0; y < this.worldHeight; y++) {
|
||||
try {
|
||||
store[x][z][y] = temp[x][y][z];
|
||||
}
|
||||
catch(Exception e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user