haven't commit in a while
This commit is contained in:
parent
748ed70f50
commit
faf8bc98ff
4 changed files with 314 additions and 95 deletions
|
@ -22,7 +22,14 @@ public class BackupIO
|
||||||
{
|
{
|
||||||
private static File pluginDir, backupsDir;
|
private static File pluginDir, backupsDir;
|
||||||
|
|
||||||
protected static void initialize(JavaPlugin plugin)
|
/**
|
||||||
|
* Defines two File variables: for the plugin's data folder, and for the "Backup Files"
|
||||||
|
* folder. Does not create either directory. The directories themselves are created
|
||||||
|
* as-needed, elsewhere in the plugin, during the process of saving a backup.
|
||||||
|
*
|
||||||
|
* @param plugin
|
||||||
|
*/
|
||||||
|
static void initialize(JavaPlugin plugin) //called from Main onEnable()
|
||||||
{
|
{
|
||||||
pluginDir = plugin.getDataFolder();
|
pluginDir = plugin.getDataFolder();
|
||||||
backupsDir = new File(pluginDir, "Backup Files");
|
backupsDir = new File(pluginDir, "Backup Files");
|
||||||
|
@ -30,15 +37,25 @@ public class BackupIO
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* Returns the parent directory containing the "region" destination directory, where
|
||||||
|
* the .mca files are stored. The path proceeds: backups > backup > town > world.
|
||||||
|
* This method returns the world directory.<p>
|
||||||
*
|
*
|
||||||
|
* Note: this method does not create any of these directories. All directories are
|
||||||
|
* created as-needed, elsewhere in the plugin, during the process of saving a backup.
|
||||||
|
*
|
||||||
|
* @param backup TODO
|
||||||
|
* @param town
|
||||||
* @param world
|
* @param world
|
||||||
* @param backup
|
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private static File getBackupDir(CraftWorld world, String backup)
|
private static File getDir(String backup, String town, CraftWorld world)
|
||||||
{
|
{
|
||||||
return new File(new File(backupsDir, world.getName()), backup);
|
return new File(
|
||||||
|
new File(
|
||||||
|
new File(backupsDir, backup )
|
||||||
|
, town )
|
||||||
|
, world.getName() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -51,20 +68,20 @@ public class BackupIO
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public static void backup(
|
public static void backup(
|
||||||
CraftWorld world, String backup, CraftChunk... chunks)
|
String backup, String town, CraftWorld world, CraftChunk... chunks)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
final World worldNMS = world.getHandle();
|
final World worldNMS = world.getHandle();
|
||||||
Chunk chunkNMS;
|
Chunk chunkNMS;
|
||||||
NBTTagCompound chunkNBT; // to be serialized
|
NBTTagCompound chunkNBT; // to be serialized
|
||||||
|
|
||||||
final File backupDir = getBackupDir(world, backup);
|
final File worldDir = getDir(backup, town, world);
|
||||||
int x, z;
|
int x, z;
|
||||||
RegionFile regionFile;
|
RegionFile regionFile;
|
||||||
DataOutputStream chunkPipe; // serialized to this
|
DataOutputStream chunkPipe; // serialized to this
|
||||||
|
|
||||||
/* chunkPipe is a series of data outputs pointing to a ChunkBuffer.
|
/* chunkPipe is a series of data outputs pointing to a ChunkBuffer.
|
||||||
* The internal class ChunkBuffer is defined within RegionFile, and
|
* ChunkBuffer is an internal class defined within RegionFile that
|
||||||
* extends ByteArrayOutputStream. It holds a byte[] buffer and two
|
* extends ByteArrayOutputStream. It holds a byte[] buffer and two
|
||||||
* int values representing the chunk's coordinates.
|
* int values representing the chunk's coordinates.
|
||||||
*/
|
*/
|
||||||
|
@ -76,11 +93,11 @@ public class BackupIO
|
||||||
|
|
||||||
x = chunk.getX();
|
x = chunk.getX();
|
||||||
z = chunk.getZ();
|
z = chunk.getZ();
|
||||||
regionFile = RegionFileCache.get(backupDir, x, z);
|
regionFile = RegionFileCache.get(worldDir, x, z);
|
||||||
chunkPipe = regionFile.b(x & 31, z & 31);
|
chunkPipe = regionFile.b(x & 31, z & 31);
|
||||||
|
|
||||||
/* below serializes chunkNBT and writes the bytes to chunkPipe,
|
/* below serializes chunkNBT, and writes those bytes to chunkPipe,
|
||||||
* which then, on close(), writes those bytes into the RegionFile's
|
* which then, on close(), writes the bytes into this RegionFile's
|
||||||
* internal RandomAccessFile, which points to the actual .mca file.
|
* internal RandomAccessFile, which points to the actual .mca file.
|
||||||
*/
|
*/
|
||||||
NBTCompressedStreamTools.a(chunkNBT, (DataOutput) chunkPipe);
|
NBTCompressedStreamTools.a(chunkNBT, (DataOutput) chunkPipe);
|
||||||
|
@ -94,10 +111,77 @@ public class BackupIO
|
||||||
*
|
*
|
||||||
* @param world
|
* @param world
|
||||||
* @param backup
|
* @param backup
|
||||||
* @param chunks
|
* @param chunks (chunk coords, larger half is z)
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
private static void restoreWhenSafe(CraftWorld world, String backup, long[] chunks)
|
private static void restore(
|
||||||
|
String backup, String town, CraftWorld world, long... chunks)
|
||||||
|
throws IOException
|
||||||
{
|
{
|
||||||
|
final File worldDir = getDir(backup, town, world);
|
||||||
|
|
||||||
|
int x, z;
|
||||||
|
|
||||||
|
RegionFile source;
|
||||||
|
RegionFile target;
|
||||||
|
DataInputStream dataInput;
|
||||||
|
DataOutputStream dataOutput;
|
||||||
|
|
||||||
|
int length;
|
||||||
|
byte[] buf;
|
||||||
|
|
||||||
|
/* dataInput is the end of a series of inputs, which proceed in
|
||||||
|
* the following order: ByteArrayInputStream > GZIPInputStream >
|
||||||
|
* BufferedInputStream > DataInputStream.
|
||||||
|
*
|
||||||
|
* dataOutput is a series of outputs pointing to a ChunkBuffer.
|
||||||
|
* ChunkBuffer is an internal class defined within RegionFile that
|
||||||
|
* extends ByteArrayOutputStream. It holds a byte[] buffer and two
|
||||||
|
* int values representing the chunk's coordinates.
|
||||||
|
*/
|
||||||
|
for (long chunk : chunks)
|
||||||
|
{
|
||||||
|
x = (int) chunk;
|
||||||
|
z = (int) ( chunk >> 32 );
|
||||||
|
|
||||||
|
source = RegionFileCache.get(worldDir, x, z);
|
||||||
|
target = RegionFileCache.getFromMinecraft(world, x, z);
|
||||||
|
dataInput = source.a(x & 31, z & 31);
|
||||||
|
dataOutput = target.b(x & 31, z & 31);
|
||||||
|
|
||||||
|
length = RegionFileCache.getChunkLength(source, x, z);
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------
|
||||||
|
* getChunkLength(...) attempts to read from RegionFile source's
|
||||||
|
* private .mca file. It will return length 0 if there is an error,
|
||||||
|
* otherwise it will return the length value recorded in the file.
|
||||||
|
*
|
||||||
|
* Below are two approaches to writing bytes from the source to
|
||||||
|
* the target. The first is faster, but we need to know the exact
|
||||||
|
* length of the chunk's data to use this approach.
|
||||||
|
*/
|
||||||
|
if (length > 0)
|
||||||
|
{
|
||||||
|
buf = new byte[length];
|
||||||
|
dataInput.readFully(buf);
|
||||||
|
dataOutput.write(buf);
|
||||||
|
}
|
||||||
|
/* In the case of an error, i.e. length 0, plan B is to convert the
|
||||||
|
* bytes into an NBTTagCompound, then serialize the NBTTagCompound
|
||||||
|
* back into bytes at the target location. This approach lets the
|
||||||
|
* native game handle the data as it normally would, using tools
|
||||||
|
* built for the purpose, at the cost of some extra effort.
|
||||||
|
*/
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NBTCompressedStreamTools.a(
|
||||||
|
NBTCompressedStreamTools.a(dataInput),
|
||||||
|
(java.io.DataOutput) dataOutput);
|
||||||
|
}
|
||||||
|
dataOutput.close(); //writes to the target file
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,26 +192,9 @@ public class BackupIO
|
||||||
* @param world
|
* @param world
|
||||||
* @param backup
|
* @param backup
|
||||||
*/
|
*/
|
||||||
private static void restoreWhenSafe(CraftWorld world, String backup)
|
private static void restoreAll(CraftWorld world, String backup)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
File worldDir = new File(backupsDir, world.getName());
|
|
||||||
File backupDir = new File(worldDir, backup);
|
|
||||||
File regionDir = new File(backupDir, "region");
|
|
||||||
|
|
||||||
if (!regionDir.exists() ||
|
|
||||||
!regionDir.isDirectory())
|
|
||||||
return;
|
|
||||||
|
|
||||||
String[] regionFileNames = regionDir.list();
|
|
||||||
if (regionFileNames == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (String regionFileName : regionFileNames)
|
|
||||||
{
|
|
||||||
//TODO BLAHAHAHABLHABLHBALJHBFLJDHBFKWYBFKUHEBF
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
98
src/simpleWarBackup/ChunkCoordsListOLD.java
Normal file
98
src/simpleWarBackup/ChunkCoordsListOLD.java
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
package simpleWarBackup;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.bukkit.configuration.InvalidConfigurationException;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
public class ChunkCoordsListOLD
|
||||||
|
{
|
||||||
|
private static final YamlConfiguration yml = new YamlConfiguration();
|
||||||
|
private static final char ps = yml.options().pathSeparator();
|
||||||
|
private static File file;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*
|
||||||
|
* @param plugin
|
||||||
|
*/
|
||||||
|
private static void initialize(JavaPlugin plugin)
|
||||||
|
{
|
||||||
|
file = new File(plugin.getDataFolder(), "Chunks.yml");
|
||||||
|
|
||||||
|
/* "Garbage Bin" contains the names of backups that have already been fully
|
||||||
|
* written back into the game world, and are presumably no longer needed.
|
||||||
|
* Each entry includes a timestamp, and is deleted after 30 days.
|
||||||
|
*
|
||||||
|
* "Storage" lists by coordinates the chunks stored in each of the backups.
|
||||||
|
* Coordinates are stored as longs, with the smaller half representing x and
|
||||||
|
* the larger half representing z.
|
||||||
|
*
|
||||||
|
* "Queue" lists by coordinates the chunks in each of the backups that are
|
||||||
|
* slated to be written back into the game world. Coordinates are stored
|
||||||
|
* in the same manner as in "Storage."
|
||||||
|
*/
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (file.exists())
|
||||||
|
{
|
||||||
|
yml.load(file);
|
||||||
|
|
||||||
|
if (!yml.contains("Garbage Bin")) yml.createSection("Garbage Bin");
|
||||||
|
if (!yml.contains("Storage")) yml.createSection("Storage");
|
||||||
|
if (!yml.contains("Queue")) yml.createSection("Queue");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
yml.createSection("Garbage Bin");
|
||||||
|
yml.createSection("Storage");
|
||||||
|
yml.createSection("Queue");
|
||||||
|
}
|
||||||
|
yml.save(file);
|
||||||
|
}
|
||||||
|
catch(IOException | InvalidConfigurationException e) { e.printStackTrace(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static void write(String path, int chunkX)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*
|
||||||
|
* @param backup
|
||||||
|
* @param town
|
||||||
|
* @param world
|
||||||
|
* @param chunks (chunk coords)
|
||||||
|
*/
|
||||||
|
static void backup(String backup, String town, String world, long... chunks)
|
||||||
|
{
|
||||||
|
String path = "Storage" + ps + backup + ps + town + ps + world;
|
||||||
|
|
||||||
|
int x, z;
|
||||||
|
int[] rows;
|
||||||
|
|
||||||
|
for (long chunk : chunks)
|
||||||
|
{
|
||||||
|
x = (int) chunk;
|
||||||
|
z = (int) ( chunk >> 32 );
|
||||||
|
|
||||||
|
//write(path + ps + (x >> 5) + ", " + (z >> 5) + ps + (z & 31));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void queue(String backup, String town, String world, long... chunks)
|
||||||
|
{
|
||||||
|
yml.set("Queue" + ps + backup + ps + town + ps + world, chunks);
|
||||||
|
}
|
||||||
|
}
|
6
src/simpleWarBackup/RegionChunkList.java
Normal file
6
src/simpleWarBackup/RegionChunkList.java
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
package simpleWarBackup;
|
||||||
|
|
||||||
|
public class RegionChunkList
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -20,7 +20,7 @@ import net.minecraft.server.v1_12_R1.World;
|
||||||
*/
|
*/
|
||||||
public final class RegionFileCache
|
public final class RegionFileCache
|
||||||
{
|
{
|
||||||
private static final int cap = 16; //capacity - how many regionFiles to keep cached
|
private static final int cap = 32; //capacity - how many regionFiles to keep cached
|
||||||
private static final Map<File, RegionFile> cache = new HashMap<File, RegionFile>();
|
private static final Map<File, RegionFile> cache = new HashMap<File, RegionFile>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,7 +45,7 @@ public final class RegionFileCache
|
||||||
* that the cache contains fewer than 16 RegionFiles, and, finding 16 or more, calls
|
* that the cache contains fewer than 16 RegionFiles, and, finding 16 or more, calls
|
||||||
* {@link #clearCache() RegionFileCache.clearCache()}.
|
* {@link #clearCache() RegionFileCache.clearCache()}.
|
||||||
*
|
*
|
||||||
* @param backupDir where to look for a "region" folder
|
* @param backupDir parent folder containing the "region" folder
|
||||||
* @param x global chunk coordinate x
|
* @param x global chunk coordinate x
|
||||||
* @param z global chunk coordinate z
|
* @param z global chunk coordinate z
|
||||||
* @return
|
* @return
|
||||||
|
@ -66,7 +66,7 @@ public final class RegionFileCache
|
||||||
|
|
||||||
regionFile = new RegionFile(mcaFile);
|
regionFile = new RegionFile(mcaFile);
|
||||||
RegionFileCache.cache.put(mcaFile, regionFile);
|
RegionFileCache.cache.put(mcaFile, regionFile);
|
||||||
RegionFileCache.cacheRAF(mcaFile, regionFile);
|
RegionFileCache.cacheChunkAccess(mcaFile, regionFile);
|
||||||
return regionFile;
|
return regionFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ public final class RegionFileCache
|
||||||
catch (IOException e) { e.printStackTrace(); }
|
catch (IOException e) { e.printStackTrace(); }
|
||||||
}
|
}
|
||||||
RegionFileCache.cache.clear();
|
RegionFileCache.cache.clear();
|
||||||
RegionFileCache.cacheRAF.clear();
|
RegionFileCache.cacheChunkAccess.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -114,77 +114,35 @@ public final class RegionFileCache
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO
|
|
||||||
*
|
|
||||||
* @param world
|
|
||||||
* @param x
|
|
||||||
* @param z
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static RegionFile getFromMinecraft(World world, int x, int z)
|
|
||||||
{
|
|
||||||
/* root directory of the world, the directory
|
|
||||||
* sharing the world's name and holding its
|
|
||||||
* data. 'region' folder is found in here.
|
|
||||||
*/
|
|
||||||
File dir = world.getDataManager().getDirectory();
|
|
||||||
|
|
||||||
return net.minecraft.server.v1_12_R1.RegionFileCache.a(dir, x, z);
|
/*=================================Chunk Access=================================*/
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Secondary cache, for holding references to the private fields "c" and "d" in each
|
||||||
|
* RegionFile cached above. TODO write more
|
||||||
/*---------------------------------Chunk Access---------------------------------*/
|
|
||||||
|
|
||||||
/* RegionFiles keep their actual .mca files private, but those bytes can be useful
|
|
||||||
* to read. The auxiliary cache below stores, for each cached RegionFile, a read-only
|
|
||||||
* RandomAccessFile pointing to the .mca file, and an int[] storing the offset values
|
|
||||||
* for each chunk's bytes within the file.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private static Map<RegionFile,
|
private static Map<RegionFile,
|
||||||
ChunkAccess> cacheRAF = new HashMap<RegionFile,
|
ChunkAccess> cacheChunkAccess = new HashMap<RegionFile,
|
||||||
ChunkAccess>();
|
ChunkAccess>();
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO
|
|
||||||
*/
|
|
||||||
public static class ChunkAccess
|
|
||||||
{
|
|
||||||
//private static Field offsetField = RegionFile.class.getDeclaredField("d");
|
|
||||||
|
|
||||||
final RandomAccessFile bytes;
|
|
||||||
final int[] offsets;
|
|
||||||
|
|
||||||
ChunkAccess(RandomAccessFile bytes, int[] chunkOffsets)
|
|
||||||
{
|
|
||||||
this.bytes = bytes;
|
|
||||||
this.offsets = chunkOffsets;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* TODO
|
||||||
*
|
*
|
||||||
* @param file
|
* @param file
|
||||||
* @param regionFile
|
* @param regionFile
|
||||||
*/
|
*/
|
||||||
private static void cacheRAF(File file, RegionFile regionFile)
|
private static void cacheChunkAccess(File file, RegionFile regionFile)
|
||||||
{
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
cacheChunkAccess.put(regionFile, new ChunkAccess(regionFile));
|
||||||
}
|
}
|
||||||
|
catch (FileNotFoundException |
|
||||||
|
IllegalAccessException |
|
||||||
/**
|
IllegalArgumentException e)
|
||||||
* TODO
|
|
||||||
*
|
|
||||||
* @param regionFile
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static RandomAccessFile getRAF(RegionFile regionFile)
|
|
||||||
{
|
{
|
||||||
return null;//TODO
|
e.printStackTrace();//TODO
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -196,8 +154,98 @@ public final class RegionFileCache
|
||||||
* @param z
|
* @param z
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static int getChunkByteLength(RegionFile regionFile, int x, int z)
|
public static int getChunkLength(RegionFile regionFile, int x, int z)
|
||||||
{
|
{
|
||||||
return 0;//TODO
|
ChunkAccess access = cacheChunkAccess.get(regionFile);
|
||||||
|
|
||||||
|
/* "offset" refers to the location of the chunk's bytes
|
||||||
|
* within the .mca file - or how many bytes into the file
|
||||||
|
* to seek when reading - divided by 4096.
|
||||||
|
*/
|
||||||
|
int offset;
|
||||||
|
|
||||||
|
/* The first four bytes at that location, the first four
|
||||||
|
* bytes of the chunk's data, are an int recording the
|
||||||
|
* chunk's length in bytes, not including those four.
|
||||||
|
*
|
||||||
|
* The next byte represents compression scheme. This byte,
|
||||||
|
* like the four previous bytes, is omitted when the game
|
||||||
|
* reads a chunk's data.
|
||||||
|
*
|
||||||
|
* This method returns the length of data actually read.
|
||||||
|
*/
|
||||||
|
if (access != null && (offset = access.offset[x + z * 32]) > 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
access.bytes.seek(offset * 4096);
|
||||||
|
return access.bytes.readInt() - 1;
|
||||||
}
|
}
|
||||||
|
catch (IOException e) { e.printStackTrace(); }
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gives access to the private fields {@code int[] d}, and {@code RandomAccessFile c},
|
||||||
|
* within a RegionFile object. The names of these fields may change in new releases of
|
||||||
|
* Spigot. TODO explain what both of those fields are
|
||||||
|
*/
|
||||||
|
private static class ChunkAccess
|
||||||
|
{
|
||||||
|
static final Field offsetField;
|
||||||
|
final int[] offset;
|
||||||
|
|
||||||
|
static final Field bytesField;
|
||||||
|
final RandomAccessFile bytes;
|
||||||
|
|
||||||
|
static
|
||||||
|
{
|
||||||
|
Field tmp1 = null;
|
||||||
|
Field tmp2 = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
tmp1 = RegionFile.class.getDeclaredField("d");
|
||||||
|
tmp1.setAccessible(true);
|
||||||
|
|
||||||
|
tmp2 = RegionFile.class.getDeclaredField("c");
|
||||||
|
tmp2.setAccessible(true);
|
||||||
|
}
|
||||||
|
catch (NoSuchFieldException | SecurityException e)
|
||||||
|
{
|
||||||
|
/* TODO take more drastic action. Either
|
||||||
|
* Field missing would mean that Minecraft
|
||||||
|
* has refactored, breaking the whole plugin
|
||||||
|
*/
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
offsetField = tmp1;
|
||||||
|
bytesField = tmp2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new DataAccess object, which holds references to the private variables
|
||||||
|
* {@code int[] d} and {@code RandomAccessFile c} within the given RegionFile. Variables
|
||||||
|
* are accessed by reflection. TODO write more
|
||||||
|
*
|
||||||
|
* @param regionFile the RegionFile whose chunks are to be accessed
|
||||||
|
*
|
||||||
|
* @throws FileNotFoundException
|
||||||
|
* @throws IllegalAccessException
|
||||||
|
* @throws IllegalArgumentException
|
||||||
|
*/
|
||||||
|
ChunkAccess(RegionFile regionFile)
|
||||||
|
throws FileNotFoundException,
|
||||||
|
IllegalAccessException,
|
||||||
|
IllegalArgumentException
|
||||||
|
{
|
||||||
|
this.offset = (int[]) offsetField.get(regionFile);
|
||||||
|
this.bytes = (RandomAccessFile) bytesField .get(regionFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue