created RegionChunkList
This commit is contained in:
parent
d40d7a5a6f
commit
0dfa339856
4 changed files with 235 additions and 4 deletions
|
@ -156,9 +156,6 @@ public class BackupIO
|
|||
* private .mca file. It will return length 0 if there is an error
|
||||
* or there is no chunk data. Otherwise, it will return the length
|
||||
* value recorded in the file.
|
||||
*
|
||||
* below writes the backup chunk data into the target region file,
|
||||
* overwriting the current chunk data in use by the game.
|
||||
*/
|
||||
if (length > 0)
|
||||
{
|
||||
|
|
147
src/simpleWarBackup/ChunkAccessCache.java
Normal file
147
src/simpleWarBackup/ChunkAccessCache.java
Normal file
|
@ -0,0 +1,147 @@
|
|||
package simpleWarBackup;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.server.v1_12_R1.RegionFile;
|
||||
|
||||
/**
|
||||
* ---------------------------------------------------------------
|
||||
* ---------------------------------------------------------------
|
||||
* ---------------------------------------------------------------
|
||||
* ---------------------------------------------------------------
|
||||
* CURRENTLY A DUPLICATE OF THE SECONDARY CACHE IN RegionFileCache
|
||||
* ---------------------------------------------------------------
|
||||
* ---------------------------------------------------------------
|
||||
* ---------------------------------------------------------------
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
public class ChunkAccessCache
|
||||
{
|
||||
private static Map<RegionFile, Access> cache = new HashMap<RegionFile, Access>();
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
* @param file
|
||||
* @param regionFile
|
||||
*/
|
||||
static void cacheChunkAccess(File file, RegionFile regionFile)
|
||||
{
|
||||
try
|
||||
{
|
||||
cache.put(regionFile, new Access(regionFile));
|
||||
}
|
||||
catch (FileNotFoundException |
|
||||
IllegalAccessException |
|
||||
IllegalArgumentException e)
|
||||
{
|
||||
e.printStackTrace();//TODO
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
* @param regionFile
|
||||
* @param x
|
||||
* @param z
|
||||
* @return
|
||||
*/
|
||||
public static int getChunkLength(RegionFile regionFile, int x, int z)
|
||||
{
|
||||
Access access = cache.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 Access
|
||||
{
|
||||
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 Access object to hold 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
|
||||
*/
|
||||
Access(RegionFile regionFile) throws FileNotFoundException,
|
||||
IllegalAccessException,
|
||||
IllegalArgumentException
|
||||
{
|
||||
offset = (int[]) offsetField.get(regionFile);
|
||||
bytes = (RandomAccessFile) bytesField .get(regionFile);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,93 @@
|
|||
package simpleWarBackup;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.util.BitSet;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class RegionChunkList
|
||||
{
|
||||
private final File file;
|
||||
private final RandomAccessFile readwrite;
|
||||
private final BitSet chunks = new BitSet(1024);
|
||||
|
||||
private final HashMap<String, HashMap
|
||||
<String, HashMap
|
||||
<String, RegionChunkList>>> lists =
|
||||
|
||||
new HashMap<String, HashMap
|
||||
<String, HashMap
|
||||
<String, RegionChunkList>>>();
|
||||
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
* @param file
|
||||
* @throws IOException
|
||||
*/
|
||||
RegionChunkList(File file, String backup, String town, String world) throws IOException
|
||||
{
|
||||
readwrite = new RandomAccessFile((this.file = file), "rw");
|
||||
|
||||
byte[] bytes = new byte[128];
|
||||
if (readwrite.length() >= 128)
|
||||
{
|
||||
readwrite.readFully(bytes);
|
||||
|
||||
int i = 0, j, k;
|
||||
for (byte b : bytes)
|
||||
for (j = 0, k = 1; j < 8; i++, j++, k <<= 1)
|
||||
if ((b & k) == k) chunks.set(i);
|
||||
}
|
||||
else readwrite.write(bytes);
|
||||
|
||||
lists.get(backup)
|
||||
.get(town)
|
||||
.put(world, this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
* @param x
|
||||
* @param z
|
||||
* @return
|
||||
*/
|
||||
boolean isChunkStored(int x, int z)
|
||||
{
|
||||
x &= 31;
|
||||
z &= 31;
|
||||
return chunks.get(x + z * 32);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
* @param x
|
||||
* @param z
|
||||
*/
|
||||
void storeChunk(int x, int z)
|
||||
{
|
||||
x &= 31;
|
||||
z &= 31;
|
||||
chunks.set(x + z * 32);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
* @param x
|
||||
* @param z
|
||||
*/
|
||||
void markChunkAsRestored(int x, int z)
|
||||
{
|
||||
x &= 31;
|
||||
z &= 31;
|
||||
chunks.clear(x + z * 32);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -215,7 +215,7 @@ public final class RegionFileCache
|
|||
}
|
||||
catch (NoSuchFieldException | SecurityException e)
|
||||
{
|
||||
/* TODO take more drastic action. Either
|
||||
/* TODO take more drastic action? Either
|
||||
* Field missing would mean that Minecraft
|
||||
* has refactored, breaking the whole plugin
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue