package clientdata; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.nio.ByteOrder; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.HashMap; import java.util.Map; import org.apache.mina.core.buffer.IoBuffer; public class STFTable { private static Map<String, STFTable> cachedSTFs = new HashMap<String, STFTable>(); private int size; private int rowCount; private int entryCount; private byte unknown; // TODO: What is this? private static Map<Integer, Map<String, String>> entries = new HashMap<Integer, Map<String, String>>(); public int getSize() { return size; } public int getRowCount() { return rowCount; } public int getEntryCount() { return entryCount; } public byte getUnknown() { return unknown; } public static STFTable read(String stfPath) throws IOException { // If we have already loaded the STFTable, let's return that if(cachedSTFs.containsKey(stfPath)) return cachedSTFs.get(stfPath); // Let's go ahead and load the STF since it isn't in the cache File stfFile = new File("clientdata/string/en/" + stfPath); FileInputStream fileStream = new FileInputStream(stfFile); IoBuffer buffer = IoBuffer.allocate(fileStream.available(), false); buffer.setAutoExpand(true); buffer.order(ByteOrder.LITTLE_ENDIAN); buffer.put(Files.readAllBytes(stfFile.toPath())); buffer.flip(); int size = buffer.getInt(); byte unknown = buffer.get(); int rowCount = buffer.getInt(); int entryCount = buffer.getInt(); STFTable table = new STFTable(size, unknown, rowCount, entryCount); byte[] characterBuffer; String[] values = new String[entryCount]; String[] keys = new String[entryCount]; int entryNumbers[] = new int[entryCount]; int entryNumber, characters; // Read values into array. Read entryNumbers into array. for(int i = 0; i < entryCount; i++) { entryNumber = buffer.getInt(); buffer.skip(4); characters = buffer.getInt(); characterBuffer = new byte[characters]; for(int a = 0; a < characters; a++) { characterBuffer[a] = buffer.get(); // Skip a byte because value is a unicode string buffer.skip(1); } entryNumbers[i] = entryNumber; values[i] = new String(characterBuffer, StandardCharsets.UTF_8); } // Read keys into array for(int i = 0; i < entryCount; i++) { entryNumber = buffer.getInt(); characters = buffer.getInt(); characterBuffer = new byte[characters]; for(int a = 0; a < characters; a++) characterBuffer[a] = buffer.get(); // Keys are being read alphabetically and not by entry number like the values are keys[entryNumber - 1] = new String(characterBuffer, StandardCharsets.UTF_8); } Map<String, String> keySet = new HashMap<String, String>(); for(int i = 0; i < entryCount; i++) { keySet.put(keys[i], values[i]); entries.put(entryNumbers[i], keySet); } // Add our Map to the cache to prevent the same STF file from being read unnecessarily fileStream.close(); cachedSTFs.put(stfPath, table); return table; } private STFTable(int size, byte unknown, int rowCount, int entryCount) throws IOException { // TODO: A boolean whether to cache the STFTable or not? this.size = size; this.unknown = unknown; this.rowCount = rowCount; this.entryCount = entryCount; } public String getValue(String key) throws IOException { for(int i = 1; i <= entries.size() ; i++) if (entries.get(i).containsKey(key)) return entries.get(i).get(key); return null; } }