Package rakama.worldtools.io

Source Code of rakama.worldtools.io.ChunkAccess

/*
* Copyright (c) 2012, RamsesA <ramsesakama@gmail.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/

package rakama.worldtools.io;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.Collection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import net.minecraft.world.level.chunk.storage.RegionFile;
import rakama.worldtools.data.Chunk;
import rakama.worldtools.data.entity.EntityFactory;

import com.mojang.nbt.CompoundTag;
import com.mojang.nbt.NbtIo;

public class ChunkAccess
{
    protected final boolean debug = false;
    protected final boolean write_empty_chunks = false;
   
    private File regionDirectory;
    private RegionManager regionManager;
    private EntityFactory entityFactory;

    protected ChunkAccess()
    {
        regionManager = new RegionManager();
        entityFactory = EntityFactory.getDefaultFactory();
    }

    public static ChunkAccess createInstance(File directory) throws IOException
    {   
        ChunkAccess access = new ChunkAccess();
        access.init(directory);
        return access;
    }
   
    protected void init(File directory) throws IOException
    {
        if(regionDirectory != null)
            throw new IllegalStateException("Region directory already initialized!");

        if(!directory.exists())
            throw new FileNotFoundException(directory.getCanonicalPath());
       
        // get parent directory if argument is a file
        if(directory.isFile())
           directory = directory.getParentFile();

        // switch to the /region directory
        File newDirectory = new File(directory.getCanonicalPath() + "/region");
        if(newDirectory.exists())
            directory = newDirectory;
        else
            throw new FileNotFoundException(newDirectory.getCanonicalPath());

        this.regionDirectory = directory;
       
        // check for any .mca files in the current directory
        File[] files = getRegionFiles(directory);

        for(File file : files)
            addFile(file);
    }

    private static File[] getRegionFiles(File regionDirectory)
    {
        return regionDirectory.listFiles(new FilenameFilter(){
            public boolean accept(File f, String s){
                return s.endsWith(".mca");}});
    }
   
    private boolean addFile(File file)
    {
        String index = "(-??[0123456789]*)";
        Pattern pattern = Pattern.compile("r\\." + index + "\\." + index + "\\.mca");

        String name = file.getName();
        Matcher matcher = pattern.matcher(name);

        try
        {
            if(matcher.matches())
            {
                int x = Integer.parseInt(matcher.group(1));
                int z = Integer.parseInt(matcher.group(2));
                regionManager.addFile(file, x, z);
                return true;
            }
        }
        catch(NumberFormatException e)
        {
            return false;
        }

        return false;
    }
   
    public Chunk readChunk(int x, int z) throws IOException
    {
        if(debug)
            log("READ_CHUNK " + x + " " + z);
       
        DataInputStream dis = getDataInputStream(x, z);

        if(dis == null)
            return null;

        // decompress chunk
        CompoundTag tag = NbtIo.read(dis);
        Chunk chunk = Chunk.loadChunk(tag);
        dis.close();
       
        return chunk;
    }
   
    protected ManagedChunk readChunk(int x, int z, ChunkManager manager) throws IOException
    {
        if(debug)
            log("READ_CHUNK " + x + " " + z);
       
        DataInputStream dis = getDataInputStream(x, z);

        if(dis == null)
            return null;

        // decompress chunk
        CompoundTag tag = NbtIo.read(dis);
        ManagedChunk chunk = ManagedChunk.loadChunk(tag, manager);
        dis.close();
       
        if(x != chunk.getX() || z != chunk.getZ())
            chunk.fixPosition(x, z);
       
        return chunk;
    }

    public void writeChunk(Chunk chunk) throws IOException
    {
        if(debug)
            log("WRITE_CHUNK " + chunk.getX() + " " + chunk.getZ());
       
        if(!write_empty_chunks && chunk.isEmpty()
        && getDataInputStream(chunk.getX(), chunk.getZ()) == null)
            return;
       
        DataOutputStream dos = getDataOutputStream(chunk.getX(), chunk.getZ());

        if(dos == null)
            throw new IOException();

        NbtIo.write(chunk.getTag(), dos);
        dos.close();
    }

    protected DataInputStream getDataInputStream(int x, int z) throws IOException
    {
        RegionFile region = regionManager.getRegionFile(x >> 5, z >> 5);

        if(region == null)
            return null;

        return region.getChunkDataInputStream(x & 0x1F, z & 0x1F);
    }

    protected DataOutputStream getDataOutputStream(int x, int z) throws IOException
    {
        RegionFile region = regionManager.getRegionFile(x >> 5, z >> 5);

        if(region == null)
        {
            region = createRegionFile(x >> 5, z >> 5);
            if(region == null)
                throw new IOException();
        }

        return region.getChunkDataOutputStream(x & 0x1F, z & 0x1F);
    }

    private RegionFile createRegionFile(int x, int z) throws IOException
    {
        String path = regionDirectory.getCanonicalPath() + "/r." + x + "." + z + ".mca";       
        regionManager.addFile(new File(path), x, z);
        return regionManager.getRegionFile(x, z);
    }
   
    public EntityFactory getEntityFactory()
    {
        return entityFactory;
    }
   
    public Collection<RegionInfo> getRegions()
    {
        return regionManager.getRegions();
    }

    public File getRegionDirectory()
    {
        return regionDirectory;
    }
   
    protected RegionManager getRegionManager()
    {
        return regionManager;
    }
   
    public void closeAll()
    {
        regionManager.closeAll();
    }

    protected final void log(String str)
    {
        System.out.println(str);
    }

    @Override
    protected void finalize()
    {
        closeAll();
    }
}
TOP

Related Classes of rakama.worldtools.io.ChunkAccess

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.