|
@@ -1,447 +0,0 @@
|
|
|
-package com.gmail.nossr50.util.blockmeta.chunkmeta;
|
|
|
-
|
|
|
-import com.gmail.nossr50.mcMMO;
|
|
|
-import com.gmail.nossr50.util.blockmeta.conversion.BlockStoreConversionZDirectory;
|
|
|
-import org.bukkit.World;
|
|
|
-import org.bukkit.block.Block;
|
|
|
-import org.bukkit.block.BlockState;
|
|
|
-import org.bukkit.entity.Entity;
|
|
|
-
|
|
|
-import java.io.*;
|
|
|
-import java.util.*;
|
|
|
-
|
|
|
-public class HashChunkManager implements ChunkManager {
|
|
|
- private final HashMap<UUID, HashMap<Long, McMMOSimpleRegionFile>> regionFiles = new HashMap<>();
|
|
|
- public HashMap<String, ChunkStore> store = new HashMap<>();
|
|
|
- public ArrayList<BlockStoreConversionZDirectory> converters = new ArrayList<>();
|
|
|
- private final HashMap<UUID, Boolean> oldData = new HashMap<>();
|
|
|
-
|
|
|
- @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;
|
|
|
- }
|
|
|
- try (ObjectInputStream objectStream = new ObjectInputStream(in)) {
|
|
|
- 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 | ClassNotFoundException e) {
|
|
|
- e.printStackTrace();
|
|
|
- // Assume the format changed
|
|
|
- return null;
|
|
|
- //throw new RuntimeException("Unable to process chunk meta data for " + x + ", " + z, e);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @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.computeIfAbsent(key, k -> new HashMap<>());
|
|
|
-
|
|
|
- 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) { e.printStackTrace(); }
|
|
|
-
|
|
|
- if (chunkStore == null) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- store.put(world.getName() + "," + cx + "," + cz, chunkStore);
|
|
|
- }
|
|
|
-
|
|
|
- @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);
|
|
|
-
|
|
|
- //closeChunkStore(world, cx, cz);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public synchronized void saveChunk(int cx, int cz, World world) {
|
|
|
- if (world == null) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- String key = world.getName() + "," + cx + "," + cz;
|
|
|
-
|
|
|
- if (store.containsKey(key)) {
|
|
|
- ChunkStore out = store.get(world.getName() + "," + cx + "," + cz);
|
|
|
-
|
|
|
- if (!out.isDirty()) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- writeChunkStore(world, cx, cz, out);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @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();
|
|
|
-
|
|
|
- List<String> keys = new ArrayList<>(store.keySet());
|
|
|
- for (String key : keys) {
|
|
|
- String[] info = key.split(",");
|
|
|
- if (worldName.equals(info[0])) {
|
|
|
- try {
|
|
|
- saveChunk(Integer.parseInt(info[1]), Integer.parseInt(info[2]), world);
|
|
|
- }
|
|
|
- catch (Exception e) {
|
|
|
- // Ignore
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public synchronized void unloadWorld(World world) {
|
|
|
- if (world == null) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- String worldName = world.getName();
|
|
|
-
|
|
|
- List<String> keys = new ArrayList<>(store.keySet());
|
|
|
- for (String key : keys) {
|
|
|
- String[] info = key.split(",");
|
|
|
- if (worldName.equals(info[0])) {
|
|
|
- try {
|
|
|
- unloadChunk(Integer.parseInt(info[1]), Integer.parseInt(info[2]), world);
|
|
|
- }
|
|
|
- catch (Exception e) {
|
|
|
- // Ignore
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- closeAll();
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public synchronized void loadWorld(World world) {}
|
|
|
-
|
|
|
- @Override
|
|
|
- public synchronized void saveAll() {
|
|
|
- closeAll();
|
|
|
-
|
|
|
- for (World world : mcMMO.p.getServer().getWorlds()) {
|
|
|
- saveWorld(world);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public synchronized void unloadAll() {
|
|
|
- closeAll();
|
|
|
-
|
|
|
- for (World world : mcMMO.p.getServer().getWorlds()) {
|
|
|
- unloadWorld(world);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public synchronized boolean isTrue(int x, int y, int z, World world) {
|
|
|
- if (world == null) {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- int cx = x >> 4;
|
|
|
- int cz = z >> 4;
|
|
|
-
|
|
|
- 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 boolean isTrue(BlockState blockState) {
|
|
|
- if (blockState == null) {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- return isTrue(blockState.getX(), blockState.getY(), blockState.getZ(), blockState.getWorld());
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public synchronized void setTrue(int x, int y, int z, World world) {
|
|
|
- if (world == null) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- int cx = x >> 4;
|
|
|
- int cz = z >> 4;
|
|
|
-
|
|
|
- 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 void setTrue(BlockState blockState) {
|
|
|
- if (blockState == null) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- setTrue(blockState.getX(), blockState.getY(), blockState.getZ(), blockState.getWorld());
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public synchronized void setFalse(int x, int y, int z, World world) {
|
|
|
- if (world == null) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- int cx = x >> 4;
|
|
|
- int cz = z >> 4;
|
|
|
-
|
|
|
- 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 setFalse(BlockState blockState) {
|
|
|
- if (blockState == null) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- setFalse(blockState.getX(), blockState.getY(), blockState.getZ(), blockState.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 || !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;
|
|
|
- }
|
|
|
-}
|