Skip to content

Instantly share code, notes, and snippets.

@lmcintyre
Created June 30, 2020 19:15
Show Gist options
  • Save lmcintyre/be5f1dd03574f97873cffca7b38c3558 to your computer and use it in GitHub Desktop.
Save lmcintyre/be5f1dd03574f97873cffca7b38c3558 to your computer and use it in GitHub Desktop.
package com.fragmenterworks.ffxivextract;
import com.fragmenterworks.ffxivextract.models.SqPack_IndexFile;
import com.fragmenterworks.ffxivextract.storage.HashDatabase;
import java.io.*;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class MassPathSearcher {
private static final String basePath = "C:\\Program Files (x86)\\SquareEnix\\Final Fantasy XIV - A Realm Reborn\\game\\";
private static SqPack_IndexFile currentIndexFile;
private static String loadedCat = "";
static int lastFolder = 0;
static int lastFile = 0;
private static HashMap<String, String> folderToIndexMap = new HashMap<String, String>() {{1
put("common", "C:\\Program Files (x86)\\SquareEnix\\Final Fantasy XIV - A Realm Reborn\\game\\sqpack\\ffxiv\\000000.win32.index");
put("bgcommon", "C:\\Program Files (x86)\\SquareEnix\\Final Fantasy XIV - A Realm Reborn\\game\\sqpack\\ffxiv\\010000.win32.index");
put("bg", "C:\\Program Files (x86)\\SquareEnix\\Final Fantasy XIV - A Realm Reborn\\game\\sqpack\\ffxiv\\020000.win32.index");
put("cut", "C:\\Program Files (x86)\\SquareEnix\\Final Fantasy XIV - A Realm Reborn\\game\\sqpack\\ffxiv\\030000.win32.index");
put("chara", "C:\\Program Files (x86)\\SquareEnix\\Final Fantasy XIV - A Realm Reborn\\game\\sqpack\\ffxiv\\040000.win32.index");
put("shader", "C:\\Program Files (x86)\\SquareEnix\\Final Fantasy XIV - A Realm Reborn\\game\\sqpack\\ffxiv\\050000.win32.index");
put("ui", "C:\\Program Files (x86)\\SquareEnix\\Final Fantasy XIV - A Realm Reborn\\game\\sqpack\\ffxiv\\060000.win32.index");
put("sound", "C:\\Program Files (x86)\\SquareEnix\\Final Fantasy XIV - A Realm Reborn\\game\\sqpack\\ffxiv\\070000.win32.index");
put("vfx", "C:\\Program Files (x86)\\SquareEnix\\Final Fantasy XIV - A Realm Reborn\\game\\sqpack\\ffxiv\\080000.win32.index");
// put("ui_script", "C:\\Program Files (x86)\\SquareEnix\\Final Fantasy XIV - A Realm Reborn\\game\\sqpack\\ffxiv\\090000.win32.index");
put("exd", "C:\\Program Files (x86)\\SquareEnix\\Final Fantasy XIV - A Realm Reborn\\game\\sqpack\\ffxiv\\0A0000.win32.index");
put("game_script", "C:\\Program Files (x86)\\SquareEnix\\Final Fantasy XIV - A Realm Reborn\\game\\sqpack\\ffxiv\\0B0000.win32.index");
// put("test", "C:\\Program Files (x86)\\SquareEnix\\Final Fantasy XIV - A Realm Reborn\\game\\sqpack\\ffxiv\\120000.win32.index");
put("_debug", "C:\\Program Files (x86)\\SquareEnix\\Final Fantasy XIV - A Realm Reborn\\game\\sqpack\\ffxiv\\130000.win32.index");
}};
private static String[] categories = new String[] {
"common",
"bgcommon",
"bg",
"cut",
"chara",
"shader",
"ui",
"sound",
"vfx",
// "ui_script",
"exd",
// "game_script",
"test",
"_debug"
};
private static HashMap<String, char[]> preCatBlackListMap = new HashMap<String, char[]>() {{
put("common/", new char[] {'g', '/'});
put("bg/", new char[] {'_'});
put("vfx/", new char[] {'_', '/'});
put("sound/", new char[] {'_'});
}};
public static void main(String[] args) throws Exception {
HashDatabase.init();
String outpath = "C:\\Users\\Liam\\Desktop\\MassSearch\\";
// for (String cat : categories) {
for (int i = 0; i < categories.length; i++) {
String cat = categories[i];
loadIndexForCategory(cat);
// for (String cat2 : categories) {
String cat2 = "ex1";
String catOut = outpath + "search_" + cat + "_" + cat2 + ".txt";
List<String> results = doStringSearch(cat2 + "/");
Files.write(Paths.get(catOut), results);
System.out.println("\nwrote " + results.size() + " paths to " + catOut);
// }
}
}
private static List<String> doStringSearch(String string) {
ArrayList<String> matches = new ArrayList<>();
for (int i = lastFolder; i < currentIndexFile.getPackFolders().length; i++) {
SqPack_IndexFile.SqPack_Folder f = currentIndexFile.getPackFolders()[i];
for (int j = lastFile; j < f.getFiles().length; j++) {
SqPack_IndexFile.SqPack_File fi = f.getFiles()[j];
byte[] data;
try {
data = currentIndexFile.extractFile(fi.dataoffset, null);
// System.out.print(".");
if (data == null)
continue;
for (int i2 = 0; i2 < data.length - string.length(); i2++) {
for (int j2 = 0; j2 < string.length(); j2++) {
if (Character.toLowerCase(data[i2 + j2]) == Character.toLowerCase(string.charAt(j2))) {
if (j2 == string.length() - 1 && prevCharValid(string, (char) data[i2 - 1])) {
int length = 100;
StringBuilder sbpre = new StringBuilder();
StringBuilder sbpost = new StringBuilder();
try {
for (int q = 1; q < length && (char) Character.toLowerCase(data[i2 + j2 + q]) != '\u0000'; q++)
sbpost.append((char) Character.toLowerCase(data[i2 + j2 + q]));
for (int q = 1; q < length && (char) Character.toLowerCase(data[i2 - q]) != '\u0000'; q++)
sbpre.append((char) Character.toLowerCase(data[i2 - q]));
} catch (IndexOutOfBoundsException ignored) {}
String path = clean(sbpre.reverse().toString().concat(string.concat(sbpost.toString())));
// String path = clean(string.concat(sbpost.toString()));
matches.add(path);
}
} else
break;
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return matches;
}
private static boolean prevCharValid(String cat, char prev) {
char[] map = preCatBlackListMap.getOrDefault(cat, null);
if (map == null)
return true;
else
for (char p : map)
if (prev == p)
return false;
return true;
}
private static String clean(String toClean) {
// strips off all non-ASCII characters
toClean = toClean.replaceAll("[^\\x00-\\x7F]", "");
// erases all the ASCII control characters
toClean = toClean.replaceAll("[\\p{Cntrl}&&[^\r\n\t]]", "");
// removes non-printable characters from Unicode
toClean = toClean.replaceAll("\\p{C}", "");
return toClean.trim();
}
private static String getCategory(String path) {
int index = path.indexOf("/");
if (index < 0)
return "null";
return path.substring(0, index);
}
private static boolean isCategoryValid(String path) {
String cat = getCategory(path);
return cat.equalsIgnoreCase("chara") ||
cat.equalsIgnoreCase("bg") ||
cat.equalsIgnoreCase("common") ||
cat.equalsIgnoreCase("bgcommon") ||
cat.equalsIgnoreCase("cut") ||
cat.equalsIgnoreCase("shader") ||
cat.equalsIgnoreCase("ui") ||
cat.equalsIgnoreCase("sound") ||
cat.equalsIgnoreCase("vfx") ||
cat.equalsIgnoreCase("ui_script") ||
cat.equalsIgnoreCase("exd") ||
cat.equalsIgnoreCase("game_script") ||
cat.equalsIgnoreCase("_debug");
}
private static void loadIndexForCategory(String cat) throws Exception {
String path = folderToIndexMap.get(cat);
currentIndexFile = new SqPack_IndexFile(path, false);
loadedCat = cat;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment