Package org.getspout.spoutapi.chunkstore

Source Code of org.getspout.spoutapi.chunkstore.SimpleChunkDataManager

/*
* This file is part of SpoutcraftPlugin.
*
* Copyright (c) 2011 SpoutcraftDev <http://spoutcraft.org//>
* SpoutcraftPlugin is licensed under the GNU Lesser General Public License.
*
* SpoutcraftPlugin is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SpoutcraftPlugin is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.getspout.spoutapi.chunkstore;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

import gnu.trove.map.hash.TIntObjectHashMap;
import gnu.trove.map.hash.TLongObjectHashMap;

import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;

import org.getspout.spoutapi.chunkdatamanager.ChunkDataManager;
import org.getspout.spoutapi.inventory.ItemMap;
import org.getspout.spoutapi.io.store.FlatFileStore;

public class SimpleChunkDataManager implements ChunkDataManager {
  private ChunkStore chunkStore = new ChunkStore();
  private HashMap<UUID, TLongObjectHashMap<ChunkMetaData>> chunkMetaDataLoaded = new HashMap<UUID, TLongObjectHashMap<ChunkMetaData>>();
  private HashMap<UUID, ItemMap> worldItemMaps = new HashMap<UUID, ItemMap>();

  public void closeAllFiles() {
    chunkStore.closeAll();
  }

  public ChunkMetaData loadChunk(Chunk c) {
    return loadChunk(c.getWorld(), c.getX(), c.getZ());
  }

  public ChunkMetaData loadChunk(World world, int x, int z) {
    ChunkMetaData md = getMetaData(world, x, z, true, true);
    return md;
  }

  public boolean loadWorldChunks(World w) {
    Chunk[] chunks = w.getLoadedChunks();

    boolean loaded = false;

    for (Chunk c : chunks) {
      loaded |= loadChunk(c) != null;
    }

    return loaded;
  }

  public boolean loadAllChunks() {
    List<World> worlds = Bukkit.getServer().getWorlds();

    boolean loaded = false;

    for (World w : worlds) {
      loaded |= loadWorldChunks(w);
    }

    return loaded;
  }

  public boolean saveChunk(Chunk c) {
    return saveChunk(c.getWorld(), c.getX(), c.getZ());
  }
 
  public boolean saveChunk(Chunk c, boolean remove) {
    return saveChunk(c.getWorld(), c.getX(), c.getZ(), remove);
  }

  public boolean saveChunk(World w, int x, int z) {
    ChunkMetaData md = getMetaData(w, x, z, false, false);
    if (md != null) {
      chunkStore.writeChunkMetaData(w, x, z, md);
      return true;
    } else {
      return false;
    }
  }

  public boolean saveChunk(World w, int x, int z, boolean remove) {
    boolean saved = saveChunk(w, x, z);
    if (saved) {
      if (remove) {
        final TLongObjectHashMap<ChunkMetaData> chunks = chunkMetaDataLoaded.get(w.getUID());
        if (chunks == null) {
          return false;
        }

        chunks.remove((((long) x) << 32) | (((long) z) & 0xFFFFFFFFL));
      }
    } else {
      return false;
    }
    return true;
  }

  public boolean closeChunk(World w, int x, int z) {
    ChunkMetaData md = getMetaData(w, x, z, false, false);

    if (md != null) {
      chunkStore.closeChunkMetaData(w, x, z);
      return true;
    } else {
      return false;
    }
  }

  public boolean unloadWorldChunks(World world) {
    return saveWorldChunks(world, true);
  }

  public boolean saveWorldChunks(World world) {
    return saveWorldChunks(world, false);
  }

  public boolean saveWorldChunks(World world, boolean unload) {
    boolean unloaded = false;
    synchronized (chunkMetaDataLoaded) {
      TLongObjectHashMap<ChunkMetaData> worldChunks = chunkMetaDataLoaded.get(world.getUID());

      if (worldChunks == null) {
        return false;
      }

      Collection<ChunkMetaData> chunks = worldChunks.valueCollection();

      for (ChunkMetaData md : chunks) {
        unloaded |= saveChunk(world, md.getChunkX(), md.getChunkZ());
        if (unload) {
          closeChunk(world, md.getChunkX(), md.getChunkZ());
        }
      }

      worldChunks.clear();
    }
    return unloaded;
  }

  public boolean unloadAllChunks() {
    List<World> worlds = Bukkit.getServer().getWorlds();

    boolean unloaded = false;

    for (World world : worlds) {
      unloaded |= saveWorldChunks(world);
    }

    return unloaded;
  }

  @Override
  public Serializable setBlockData(String id, World world, int x, int y, int z, Serializable data) {
    ChunkMetaData md = getMetaData(world, x >> 4, z >> 4, true, true);

    return md.putBlockData(id, x, y, z, data);
  }

  @Override
  public Serializable getBlockData(String id, World world, int x, int y, int z) {
    ChunkMetaData md = getMetaData(world, x >> 4, z >> 4, true, false);

    if (md == null) {
      return null;
    }

    return md.getBlockData(id, x, y, z);
  }

  public Serializable removeBlockData(String id, World world, int x, int y, int z) {
    ChunkMetaData md = getMetaData(world, x >> 4, z >> 4, true, false);

    if (md == null) {
      return null;
    }

    return md.removeBlockData(id, x, y, z);
  }

  @Override
  public Serializable setChunkData(String id, World world, int x, int z, Serializable data) {
    ChunkMetaData md = getMetaData(world, x, z, true, true);

    return md.putChunkData(id, data);
  }

  @Override
  public Serializable getChunkData(String id, World world, int x, int z) {
    ChunkMetaData md = getMetaData(world, x, z, true, false);

    if (md == null) {
      return null;
    }

    return md.getChunkData(id);
  }

  @Override
  public Serializable removeChunkData(String id, World world, int x, int z) {
    ChunkMetaData md = getMetaData(world, x, z, true, false);

    if (md == null) {
      return null;
    }

    return md.removeChunkData(id);
  }

  @Override
  public short[] getCustomBlockIds(World world, int x, int z) {
    ChunkMetaData md = getMetaData(world, x, z, true, false);

    if (md == null) {
      return null;
    }

    return md.getCustomBlockIds();
  }

  @Override
  public void setCustomBlockIds(World world, int x, int z, short[] ids) {
    ChunkMetaData md = getMetaData(world, x, z, true, true);

    md.setCustomBlockIds(ids);
  }

  @Override
  public byte[] getCustomBlockData(World world, int x, int z) {
    ChunkMetaData md = getMetaData(world, x, z, true, false);

    if (md == null) {
      return null;
    }

    return md.getCustomBlockData();
  }

  @Override
  public void setCustomBlockData(World world, int x, int z, byte[] ids) {
    ChunkMetaData md = getMetaData(world, x, z, true, true);

    md.setCustomBlockData(ids);
  }

  private ChunkMetaData getMetaData(World world, int x, int z, boolean load, boolean loadOrCreate) {
    long key = (((long) x) << 32) | (((long) z) & 0xFFFFFFFFL);
    UUID uid = world.getUID();
    ChunkMetaData md = null;
    synchronized (chunkMetaDataLoaded) {
      TLongObjectHashMap<ChunkMetaData> worldChunks = chunkMetaDataLoaded.get(uid);
      if (worldChunks == null) {
        worldChunks = new TLongObjectHashMap<ChunkMetaData>();
        chunkMetaDataLoaded.put(uid, worldChunks);
      }

      md = worldChunks.get(key);

      if (md == null && (load || loadOrCreate)) {
        try {
          md = chunkStore.readChunkMetaData(world, x, z);
          if (md != null) {
            if (!md.getWorldUID().equals(world.getUID()) || md.getChunkX() != x || md.getChunkZ() != z) {
              System.err.println("Chunk data mismatch!");
              System.err.println("Expected: " + world.getUID() + " " + x + " " + z);
              System.err.println("Actual: " + md.getWorldUID() + " " + md.getChunkX() + " " + md.getChunkZ());
              //throw new RuntimeException("Chunk meta data stored in wrong location");
            }
            md.setWorldItemMap(getWorldItemMap(world));
          }
        } catch (IOException e) {
          e.printStackTrace();
          return null;
        }

        if (md == null && loadOrCreate) {
          md = new ChunkMetaData(world.getUID(), getWorldItemMap(world), x, z);
        }

        if (md != null) {
          worldChunks.put(key, md);
        }
      }
    }

    return md;
  }

  private ItemMap getWorldItemMap(World world) {
    UUID uid = world.getUID();
    ItemMap worldItemMap = worldItemMaps.get(uid);
    if (worldItemMap == null) {
      File dir = new File(world.getWorldFolder(), "spout_meta");
      dir.mkdirs();

      FlatFileStore<Integer> fs = new FlatFileStore<Integer>(new File(dir, "worldItemMap.txt"), Integer.class);
      fs.load();
      worldItemMap = new ItemMap(ItemMap.getRootMap(), fs, null);
    }
    worldItemMaps.put(uid, worldItemMap);
    return worldItemMap;
  }

  public int getStringId(String string) {
    return ItemMap.getRootMap().register(string);
  }

  @Override
  public ItemMap getItemMap(World world) {
    return worldItemMaps.get(world.getUID());
  }
}
TOP

Related Classes of org.getspout.spoutapi.chunkstore.SimpleChunkDataManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.