1package com.osroyale.fs.cache;
3import com.google.common.base.Preconditions;
4import com.osroyale.fs.cache.archive.Archive;
6import java.io.IOException;
7import java.nio.ByteBuffer;
8import java.nio.channels.SeekableByteChannel;
9import java.nio.file.Files;
10import java.nio.file.Path;
11import java.nio.file.Paths;
12import java.util.Objects;
13import java.util.zip.CRC32;
15import static java.nio.file.StandardOpenOption.READ;
16import static java.nio.file.StandardOpenOption.WRITE;
49public final class FileSystem {
94 private static final int MAXIMUM_ARCHIVES = 9;
97 private static final int MAXIMUM_INDICES = 256;
100 private static final String DATA_PREFIX =
"main_file_cache.dat";
103 private static final String INDEX_PREFIX =
"main_file_cache.idx";
106 private final Cache[] caches;
109 private final Archive[] archives;
112 private ByteBuffer archiveHashes;
123 private FileSystem(
Cache[] caches,
Archive[] archives) {
124 this.caches = caches;
125 this.archives = archives;
136 public static FileSystem
create(String directory)
throws IOException {
137 Path root = Paths.get(directory);
138 Preconditions.checkArgument(Files.isDirectory(root),
"Supplied path must be a directory! " + root);
140 Path data = root.resolve(DATA_PREFIX);
141 Preconditions.checkArgument(Files.exists(data),
"No data file found in the specified path!");
143 SeekableByteChannel dataChannel = Files.newByteChannel(data, READ, WRITE);
148 for (
int index = 0; index < caches.length; index++) {
149 Path path = root.resolve(INDEX_PREFIX + index);
150 if (Files.exists(path)) {
151 SeekableByteChannel indexChannel = Files.newByteChannel(path, READ, WRITE);
152 caches[index] =
new Cache(dataChannel, indexChannel, index);
157 for (
int id = 1;
id < archives.length;
id++) {
158 Cache cache = Objects.requireNonNull(caches[
CONFIG_INDEX],
"Configuration cache is null - unable to decode archives");
162 return new FileSystem(caches, archives);
174 Preconditions.checkElementIndex(
id, archives.length);
175 return Objects.requireNonNull(archives[
id]);
187 Preconditions.checkElementIndex(
id, caches.length);
188 return Objects.requireNonNull(caches[
id]);
200 public ByteBuffer
getFile(
int cacheId,
int indexId)
throws IOException {
202 synchronized (cache) {
203 return cache.get(indexId);
215 synchronized (
this) {
216 if (archiveHashes !=
null) {
217 return archiveHashes.duplicate();
221 int[] crcs =
new int[MAXIMUM_ARCHIVES];
223 CRC32 crc32 =
new CRC32();
224 for (
int file = 1; file < crcs.length; file++) {
228 crc32.update(buffer);
230 crcs[file] = (int) crc32.getValue();
233 ByteBuffer buffer = ByteBuffer.allocate((crcs.length + 1) * Integer.BYTES);
236 for (
int crc : crcs) {
237 hash = (hash << 1) + crc;
244 synchronized (
this) {
245 archiveHashes = buffer.asReadOnlyBuffer();
246 return archiveHashes.duplicate();
static final int MANIFEST_ARCHIVE
static final int MIDI_INDEX
static final int ANIMATION_INDEX
Archive getArchive(int id)
static final int WORD_ARCHIVE
static final int MODEL_INDEX
ByteBuffer getFile(int cacheId, int indexId)
static final int SOUND_ARCHIVE
static final int CONFIG_INDEX
ByteBuffer getArchiveHashes()
static final int TITLE_ARCHIVE
static final int TEXTURES_ARCHIVE
static final int MAP_INDEX
static final int CONFIG_ARCHIVE
static FileSystem create(String directory)
static final int INTERFACE_ARCHIVE
static final int MEDIA_ARCHIVE
static Archive decode(ByteBuffer data)