Updated Release Archive
Updated Release Archive. Fixed Mage-killer prereqs. Removed old LETO & ConvoCC related files. Added organized spell scroll store. Fixed Gloura spellbook. Various TLK fixes. Reorganized Repo. Removed invalid user folders. Added DocGen back in.
This commit is contained in:
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/ClassEntry.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/ClassEntry.class
Normal file
Binary file not shown.
71
nwn/nwnprc/DocGen/trunk/prc/autodoc/ClassEntry.java
Normal file
71
nwn/nwnprc/DocGen/trunk/prc/autodoc/ClassEntry.java
Normal file
@@ -0,0 +1,71 @@
|
||||
package prc.autodoc;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* Data structure for a class entry.
|
||||
*/
|
||||
public class ClassEntry extends GenericEntry {
|
||||
/**
|
||||
* If <code>true</code>, this class is a base class.
|
||||
*/
|
||||
public final boolean isBase;
|
||||
|
||||
/**
|
||||
* List of BAB and saving throw values. Each list entry consists of the values
|
||||
* for the list indexth level. Order: BAB, Fort, Ref, Will.
|
||||
*/
|
||||
public final List<String[]> babSav;
|
||||
|
||||
/**
|
||||
* The list of this class's class and cross-class skills. First tuple member
|
||||
* cotnaints the class skills, the second cross-class skills.
|
||||
* Map keys are skill names.
|
||||
*/
|
||||
public final Tuple<TreeMap<String, GenericEntry>, TreeMap<String, GenericEntry>> skillList;
|
||||
|
||||
/**
|
||||
* Lists of this class's granted and selectable feats. First tuple member lists bonus feat
|
||||
* # at each level. First inner tuple member is the granted feats, second member is selectable feats.
|
||||
* Each list consists of the feats that are related to the list indexth level.
|
||||
* The map keys are feat names.
|
||||
*/
|
||||
public final Tuple<List<Integer>, Tuple<List<TreeMap<String, FeatEntry>>, List<TreeMap<String, FeatEntry>>>> featList;
|
||||
|
||||
/**
|
||||
* The alternate magic systems available to this class. Each list entry describes one
|
||||
* magic system (though there will probably never be more than one per class).
|
||||
* First member of the outer tuple is the (magic system name, magic system spell-equivalent name)
|
||||
* pair. Second member is a map keyed to spell-equivalent level, with values being maps of
|
||||
* spell-equivalent name to the spell entry.
|
||||
*/
|
||||
public final List<Tuple<Tuple<String, String>, TreeMap<Integer, TreeMap<String, SpellEntry>>>> magics;
|
||||
|
||||
/**
|
||||
* Create a new class entry.
|
||||
*
|
||||
* @param name The name of this class.
|
||||
* @param text The description of this class.
|
||||
* @param iconPath The path of this class's icon.
|
||||
* @param filePath The path of the html file that has been written for this class.
|
||||
* @param isBase If <code>true</code>, this class is a base class.
|
||||
* @param entryNum Index of the class in classes.2da.
|
||||
* @param babSav The BAB and saves of this class.
|
||||
* @param skillList The skills of this class.
|
||||
* @param featList The feats of this class.
|
||||
* @param magics The alternate magics of this class.
|
||||
*/
|
||||
public ClassEntry(String name, String text, String iconPath, String filePath,
|
||||
int entryNum, boolean isBase, List<String[]> babSav,
|
||||
Tuple<TreeMap<String, GenericEntry>, TreeMap<String, GenericEntry>> skillList,
|
||||
Tuple<List<Integer>, Tuple<List<TreeMap<String, FeatEntry>>, List<TreeMap<String, FeatEntry>>>> featList,
|
||||
List<Tuple<Tuple<String, String>, TreeMap<Integer, TreeMap<String, SpellEntry>>>> magics) {
|
||||
super(name, text, iconPath, filePath, entryNum);
|
||||
this.isBase = isBase;
|
||||
this.babSav = babSav;
|
||||
this.skillList = skillList;
|
||||
this.featList = featList;
|
||||
this.magics = magics;
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Data_2da.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Data_2da.class
Normal file
Binary file not shown.
1073
nwn/nwnprc/DocGen/trunk/prc/autodoc/Data_2da.java
Normal file
1073
nwn/nwnprc/DocGen/trunk/prc/autodoc/Data_2da.java
Normal file
File diff suppressed because it is too large
Load Diff
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Data_TLK.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Data_TLK.class
Normal file
Binary file not shown.
278
nwn/nwnprc/DocGen/trunk/prc/autodoc/Data_TLK.java
Normal file
278
nwn/nwnprc/DocGen/trunk/prc/autodoc/Data_TLK.java
Normal file
@@ -0,0 +1,278 @@
|
||||
package prc.autodoc;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.MappedByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.HashMap;
|
||||
|
||||
import static prc.Main.spinner;
|
||||
import static prc.Main.verbose;
|
||||
|
||||
/**
|
||||
* This class forms an interface for accessing TLK files in the
|
||||
* PRC automated manual generator.
|
||||
*/
|
||||
public class Data_TLK {
|
||||
private final HashMap<Integer, String> mainData = new HashMap<Integer, String>();
|
||||
private int highestEntry = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new Data_TLK on the TLK file specified.
|
||||
*
|
||||
* @param filePath The path of the TLK file to be loaded
|
||||
* @throws IllegalArgumentException <code>filePath</code> does not filePath a TLK file
|
||||
* @throws TLKReadException reading the TLK file specified does not succeed
|
||||
*/
|
||||
public Data_TLK(String filePath) {
|
||||
// Some paranoia checking for bad parameters
|
||||
if (!filePath.toLowerCase().endsWith("tlk"))
|
||||
throw new IllegalArgumentException("Non-tlk filename passed to Data_TLK: " + filePath);
|
||||
|
||||
File baseFile = new File(filePath);
|
||||
if (!baseFile.exists())
|
||||
throw new IllegalArgumentException("Nonexistent file passed to Data_TLK: " + filePath);
|
||||
if (!baseFile.isFile())
|
||||
throw new IllegalArgumentException("Nonfile passed to Data_TLK: " + filePath);
|
||||
|
||||
|
||||
// Create a RandomAccessFile for reading the TLK. Read-only
|
||||
MappedByteBuffer reader = null;
|
||||
RandomAccessFile fileReader;
|
||||
try {
|
||||
fileReader = new RandomAccessFile(baseFile, "r");
|
||||
reader = fileReader.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, fileReader.length());
|
||||
} catch (IOException e) {
|
||||
throw new TLKReadException("Cannot access TLK file: " + filePath, e);
|
||||
}
|
||||
byte[] bytes4 = new byte[4],
|
||||
bytes8 = new byte[8];
|
||||
|
||||
// Drop the path from the filename
|
||||
String fileName = baseFile.getName();
|
||||
|
||||
// Tell the user what we are doing
|
||||
if (verbose) System.out.print("Reading TLK file: " + fileName + " ");
|
||||
|
||||
try {
|
||||
// Check the header
|
||||
reader.get(bytes4);
|
||||
if (!new String(bytes4).equals("TLK "))
|
||||
throw new TLKReadException("Wrong file type field in: " + fileName);
|
||||
|
||||
// Check the version
|
||||
reader.get(bytes4);
|
||||
if (!new String(bytes4).equals("V3.0"))
|
||||
throw new TLKReadException("Wrong TLK version number in: " + fileName);
|
||||
|
||||
// Skip the language ID
|
||||
reader.position(reader.position() + 4);
|
||||
|
||||
// Read the entrycount
|
||||
int stringCount = readLittleEndianInt(reader, bytes4);
|
||||
int stringOffset = readLittleEndianInt(reader, bytes4);
|
||||
|
||||
// Read the entry lengths
|
||||
int[] stringLengths = readStringLengths(reader, stringCount);
|
||||
|
||||
// Read the strings themselves
|
||||
readStrings(reader, stringLengths, stringOffset);
|
||||
|
||||
// Store the highest string for writing back later
|
||||
highestEntry = stringLengths.length;
|
||||
} catch (IOException e) {
|
||||
throw new TLKReadException("IOException while reading TLK file: " + fileName, e);
|
||||
} finally {
|
||||
try {
|
||||
fileReader.close();
|
||||
} catch (IOException e) {
|
||||
// No idea under what conditions closing a file could fail and not cause an Error to be thrown...
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (verbose) System.out.println("- Done");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the given TLK entry.
|
||||
*
|
||||
* @param strRef the number of the entry to get
|
||||
* @return the entry string or "Bad StrRef" if the entry wasn't in the TLK
|
||||
*/
|
||||
public String getEntry(int strRef) {
|
||||
if (strRef > 0x01000000) strRef -= 0x01000000;
|
||||
String toReturn = mainData.get(strRef);
|
||||
if (toReturn == null) toReturn = Main.badStrRef;
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the given TLK entry.
|
||||
*
|
||||
* @param strRef the number of the entry to get as a string
|
||||
* @return the entry string or "Bad StrRef" if the entry wasn't in the TLK
|
||||
* @throws NumberFormatException if <code>strRef</code> cannot be converted to an integer
|
||||
*/
|
||||
public String getEntry(String strRef) {
|
||||
try {
|
||||
return getEntry(Integer.parseInt(strRef));
|
||||
} catch (NumberFormatException e) {
|
||||
return Main.badStrRef;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the given TLK entry.
|
||||
*
|
||||
* @param strRef the number of the entry to set
|
||||
* @param value the value of the entry to set
|
||||
*/
|
||||
public void setEntry(int strRef, String value) {
|
||||
if (strRef > 0x01000000) strRef -= 0x01000000;
|
||||
mainData.put(strRef, value);
|
||||
if (strRef > highestEntry)
|
||||
highestEntry = strRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the tlk file to the given XML.
|
||||
*
|
||||
* @param name the name of the resulting file, without extensions
|
||||
* @param path the path to the directory to save the file to
|
||||
* @param allowOverWrite Whether to allow overwriting existing files
|
||||
* @throws IOException if cannot overwrite, or the underlying IO throws one
|
||||
*/
|
||||
public void saveAsXML(String name, String path, boolean allowOverWrite) throws IOException {
|
||||
if (path == null || path.equals(""))
|
||||
path = "." + File.separator;
|
||||
if (!path.endsWith(File.separator))
|
||||
path += File.separator;
|
||||
|
||||
File file = new File(path + name + ".tlk.xml");
|
||||
if (file.exists() && !allowOverWrite)
|
||||
throw new IOException("File exists already: " + file.getAbsolutePath());
|
||||
|
||||
// Inform user
|
||||
if (verbose) System.out.print("Saving tlk file: " + name + " ");
|
||||
|
||||
PrintWriter writer = new PrintWriter(file);
|
||||
|
||||
//write the header
|
||||
writer.println("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
|
||||
writer.println("<!DOCTYPE tlk SYSTEM \"tlk2xml.dtd\">");
|
||||
writer.println("<tlk>");
|
||||
|
||||
//loop over each row and write it
|
||||
for (int row = 0; row < highestEntry; row++) {
|
||||
String data = mainData.get(row);
|
||||
if (data != null) {
|
||||
//replace with paired characters
|
||||
data = data.replace("&", "&"); //this must be before the others
|
||||
data = data.replace("<", "<");
|
||||
data = data.replace(">", ">");
|
||||
writer.println(" <entry id=\"" + row + "\" lang=\"en\" sex=\"m\">" + data + "</entry>");
|
||||
}
|
||||
if (verbose) spinner.spin();
|
||||
}
|
||||
|
||||
//write the footer
|
||||
writer.println("</tlk>");
|
||||
|
||||
writer.flush();
|
||||
writer.close();
|
||||
|
||||
if (verbose) System.out.println("- Done");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads the string lengths from this TLK's string data elements.
|
||||
*
|
||||
* @param reader RandomAccessFile read from
|
||||
* @param stringCount number of strings in the TLK
|
||||
* @return an array of integers containing the lengths of the strings in this TLK
|
||||
* @throws IOException if there is an error while reading from <code>reader</code>
|
||||
*/
|
||||
private int[] readStringLengths(MappedByteBuffer reader, int stringCount) throws IOException {
|
||||
int[] toReturn = new int[stringCount];
|
||||
byte[] bytes4 = new byte[4];
|
||||
int curOffset = 20; // The number of bytes in the TLK header section
|
||||
|
||||
for (int i = 0; i < stringCount; i++) {
|
||||
// Skip everything up to the length
|
||||
curOffset += 32;
|
||||
reader.position(curOffset);
|
||||
// Read the value
|
||||
toReturn[i] = readLittleEndianInt(reader, bytes4);
|
||||
// Skip to the end of the record
|
||||
curOffset += 8;
|
||||
|
||||
if (verbose) spinner.spin();
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the strings from the TLK into the hashmap.
|
||||
*
|
||||
* @param reader RandomAccessFile read from
|
||||
* @param stringLengths an array of integers containing the lengths of the strings in this TLK
|
||||
* @param curOffset the offset to start reading from in the file
|
||||
* @throws IOException if there is an error while reading from <code>reader</code>
|
||||
*/
|
||||
private void readStrings(MappedByteBuffer reader, int[] stringLengths, int curOffset) throws IOException {
|
||||
StringBuffer buffer = new StringBuffer(200);
|
||||
reader.position(curOffset);
|
||||
|
||||
for (int i = 0; i < stringLengths.length; i++) {
|
||||
if (stringLengths[i] > 0) {
|
||||
// Read the specified number of bytes, convert them into chars
|
||||
// and put them in the buffer
|
||||
for (int j = 0; j < stringLengths[i]; j++)
|
||||
buffer.append((char) (reader.get() & 0xff));
|
||||
// Store the buffer contents
|
||||
mainData.put(i, buffer.toString());
|
||||
// Wipe the buffer for next round
|
||||
buffer.delete(0, buffer.length());
|
||||
}
|
||||
if (verbose) spinner.spin();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the next 4 bytes into the given array from the TLK and then
|
||||
* writes them into an integer in inverse order.
|
||||
*
|
||||
* @param reader RandomAccessFile read from
|
||||
* @param readArray array of bytes read to. For efficiency of not having to create a new array every time
|
||||
* @return integer read
|
||||
* @throws IOException if there is an error while reading from <code>reader</code>
|
||||
*/
|
||||
private int readLittleEndianInt(MappedByteBuffer reader, byte[] readArray) throws IOException {
|
||||
int toReturn = 0;
|
||||
reader.get(readArray);
|
||||
for (int i = readArray.length - 1; i >= 0; i--) {
|
||||
// What's missing here is the implicit promotion of readArray[i] to
|
||||
// int. A byte is a signed element, and as such, has max value of 0x7f.
|
||||
toReturn = (toReturn << 8) | readArray[i] & 0xff;
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* The main method, as usual
|
||||
*
|
||||
* @param args
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
Data_TLK test = new Data_TLK(args[0]);
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/DomainEntry.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/DomainEntry.class
Normal file
Binary file not shown.
37
nwn/nwnprc/DocGen/trunk/prc/autodoc/DomainEntry.java
Normal file
37
nwn/nwnprc/DocGen/trunk/prc/autodoc/DomainEntry.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package prc.autodoc;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Data structure for a domain entry.
|
||||
*/
|
||||
public class DomainEntry extends GenericEntry {
|
||||
|
||||
/**
|
||||
* This domain's domain power, if any
|
||||
*/
|
||||
public final FeatEntry grantedFeat;
|
||||
/**
|
||||
* The domain's spells. List of spell entry.
|
||||
*/
|
||||
public final List<SpellEntry> spells;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*
|
||||
* @param name Name of the domain
|
||||
* @param text Description of the domain
|
||||
* @param iconPath Path of the domain's icon
|
||||
* @param filePath Path where the html page for this domain will be written to
|
||||
* @param entryNum domains.2da index
|
||||
* @param grantedFeat Domain power feat
|
||||
* @param spells The domain spells
|
||||
*/
|
||||
public DomainEntry(String name, String text, String iconPath, String filePath,
|
||||
int entryNum, FeatEntry grantedFeat,
|
||||
List<SpellEntry> spells) {
|
||||
super(name, text, iconPath, filePath, entryNum);
|
||||
this.grantedFeat = grantedFeat;
|
||||
this.spells = spells;
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration$1.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration$1.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration$2.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration$2.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration$3.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration$3.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration$4.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration$4.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration$5.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration$5.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration$6.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration$6.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration.class
Normal file
Binary file not shown.
1844
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration.java
Normal file
1844
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration.java
Normal file
File diff suppressed because it is too large
Load Diff
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/ErrorPrinter.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/ErrorPrinter.class
Normal file
Binary file not shown.
66
nwn/nwnprc/DocGen/trunk/prc/autodoc/ErrorPrinter.java
Normal file
66
nwn/nwnprc/DocGen/trunk/prc/autodoc/ErrorPrinter.java
Normal file
@@ -0,0 +1,66 @@
|
||||
package prc.autodoc;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* A convenience class for printing errors to both log and System.err
|
||||
*/
|
||||
public class ErrorPrinter {
|
||||
private PrintWriter writer;
|
||||
private boolean isInit = false;
|
||||
|
||||
/**
|
||||
* Initializes the ErrorPrinter.
|
||||
* Attempts to open a log file by name of "errorlog" for writing. If this
|
||||
* fails, aborts the program.
|
||||
*/
|
||||
private void init() {
|
||||
try {
|
||||
writer = new PrintWriter(new FileOutputStream("errorlog", false), true);
|
||||
isInit = true;
|
||||
} catch (Exception e) {
|
||||
System.err.println("Error while creating error logger. Yes, it's ironic. Now debug");
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prints the given string to both stderr and errorlog.
|
||||
*
|
||||
* @param toPrint string to write
|
||||
*/
|
||||
public void print(String toPrint) {
|
||||
if (!isInit)
|
||||
init();
|
||||
writer.print(toPrint);
|
||||
System.err.print(toPrint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the given string to both stderr and errorlog. In addition, adds
|
||||
* a line terminator to the end of the string.
|
||||
*
|
||||
* @param toPrint string to write
|
||||
*/
|
||||
public void println(String toPrint) {
|
||||
if (!isInit)
|
||||
init();
|
||||
writer.println(toPrint);
|
||||
System.err.println(toPrint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the given exception's stack trace to both stderr and errorlog.
|
||||
*
|
||||
* @param e exception to print
|
||||
*/
|
||||
public void printException(Exception e) {
|
||||
if (!isInit)
|
||||
init();
|
||||
e.printStackTrace(System.out);
|
||||
e.printStackTrace(writer);
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/FeatEntry.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/FeatEntry.class
Normal file
Binary file not shown.
88
nwn/nwnprc/DocGen/trunk/prc/autodoc/FeatEntry.java
Normal file
88
nwn/nwnprc/DocGen/trunk/prc/autodoc/FeatEntry.java
Normal file
@@ -0,0 +1,88 @@
|
||||
package prc.autodoc;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* Data structure for a feat or masterfeat entry.
|
||||
*/
|
||||
public class FeatEntry extends GenericEntry {
|
||||
/**
|
||||
* A list of masterfeat's children
|
||||
*/
|
||||
public TreeMap<String, FeatEntry> childFeats = new TreeMap<String, FeatEntry>();
|
||||
/**
|
||||
* A list of feats that have this feat as their prerequisite
|
||||
*/
|
||||
public TreeMap<String, FeatEntry> requiredForFeats = new TreeMap<String, FeatEntry>();
|
||||
/**
|
||||
* A list of this feat's AND prerequisites
|
||||
*/
|
||||
public TreeMap<String, FeatEntry> andRequirements = new TreeMap<String, FeatEntry>();
|
||||
/**
|
||||
* A list of this feat's OR prerequisites
|
||||
*/
|
||||
public TreeMap<String, FeatEntry> orRequirements = new TreeMap<String, FeatEntry>();
|
||||
|
||||
/**
|
||||
* This feat's masterfeat, if any
|
||||
*/
|
||||
public FeatEntry master;
|
||||
/**
|
||||
* This feat's successor, if any
|
||||
*/
|
||||
public FeatEntry successor;
|
||||
|
||||
/**
|
||||
* Whether this feat is epic, as defined by feat.2da column PreReqEpic. For masterfeats, if any of the children are epic
|
||||
*/
|
||||
public boolean isEpic;
|
||||
/**
|
||||
* Whether all of a masterfeat's children are epic. This is used to determine which menus a link to it will be printed
|
||||
*/
|
||||
public boolean allChildrenEpic;
|
||||
/**
|
||||
* Whether the feat is a class-specific feat, as defined by feat.2da column ALLCLASSESCANUSE. For masterfeats, if any of the children are class-specific
|
||||
*/
|
||||
public boolean isClassFeat;
|
||||
/**
|
||||
* Whether all of a masterfeat's children are class-specific. This is used to determine which menus a link to it will be printed
|
||||
*/
|
||||
public boolean allChildrenClassFeat;
|
||||
/**
|
||||
* Whether this feat has a successor
|
||||
*/
|
||||
public boolean isSuccessor;
|
||||
|
||||
/**
|
||||
* The feat's subradials, if any. List of feat name, icon path tuples.
|
||||
*/
|
||||
public final List<Tuple<String, String>> subradials;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*
|
||||
* @param name Name of the feat/masterfeat
|
||||
* @param text Description of the feat
|
||||
* @param iconPath Path of the feat's icon
|
||||
* @param filePath Path where the html page for this feat will be written to
|
||||
* @param entryNum feat.2da / masterfeats.2da index
|
||||
* @param isEpic Whether the feat is an epic feat
|
||||
* @param isClassFeat Whether the feat is a class-specific feat
|
||||
* @param subradials List of this feat's subradials, if any
|
||||
*/
|
||||
public FeatEntry(String name, String text, String iconPath, String filePath,
|
||||
int entryNum, boolean isEpic, boolean isClassFeat,
|
||||
List<Tuple<String, String>> subradials) {
|
||||
super(name, text, iconPath, filePath, entryNum);
|
||||
this.isEpic = isEpic;
|
||||
this.isClassFeat = isClassFeat;
|
||||
this.subradials = subradials;
|
||||
|
||||
master = null;
|
||||
successor = null;
|
||||
isSuccessor = false;
|
||||
allChildrenClassFeat = false;
|
||||
allChildrenEpic = false;
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/GenericEntry.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/GenericEntry.class
Normal file
Binary file not shown.
57
nwn/nwnprc/DocGen/trunk/prc/autodoc/GenericEntry.java
Normal file
57
nwn/nwnprc/DocGen/trunk/prc/autodoc/GenericEntry.java
Normal file
@@ -0,0 +1,57 @@
|
||||
package prc.autodoc;
|
||||
|
||||
/**
|
||||
* Data structure for a skill /domain / race / class / whatever that doesn't need
|
||||
* the extra fields used for feats & spells & skills
|
||||
*/
|
||||
public class GenericEntry implements Comparable<GenericEntry> {
|
||||
/**
|
||||
* The name of this entry.
|
||||
*/
|
||||
public final String name;
|
||||
|
||||
/**
|
||||
* The contents of this entry.
|
||||
*/
|
||||
public final String text;
|
||||
|
||||
/**
|
||||
* The path of the icon file attached to this entry.
|
||||
*/
|
||||
public final String iconPath;
|
||||
|
||||
/**
|
||||
* The path of the html file that has been written for this entry.
|
||||
*/
|
||||
public final String filePath;
|
||||
|
||||
/**
|
||||
* Index of the entry in whichever 2da defines it.
|
||||
*/
|
||||
public final int entryNum;
|
||||
|
||||
/**
|
||||
* @param name Name of the entry
|
||||
* @param text Content of the entry
|
||||
* @param iconPath Path of this entry's icon
|
||||
* @param filePath Path the generated file will be located in
|
||||
* @param entryNum Number of the
|
||||
*/
|
||||
public GenericEntry(String name, String text, String iconPath, String filePath, int entryNum) {
|
||||
this.name = name;
|
||||
this.text = text;
|
||||
this.iconPath = iconPath;
|
||||
this.filePath = filePath;
|
||||
this.entryNum = entryNum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparable implementation. Uses the name fields for comparison.
|
||||
*
|
||||
* @param other GenericEntry to compare this one to
|
||||
* @return @see java.lang.Comparable#compareTo
|
||||
*/
|
||||
public int compareTo(GenericEntry other) {
|
||||
return name.compareTo(other.name);
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Icons$1.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Icons$1.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Icons$Check.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Icons$Check.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Icons$Convert.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Icons$Convert.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Icons.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Icons.class
Normal file
Binary file not shown.
215
nwn/nwnprc/DocGen/trunk/prc/autodoc/Icons.java
Normal file
215
nwn/nwnprc/DocGen/trunk/prc/autodoc/Icons.java
Normal file
@@ -0,0 +1,215 @@
|
||||
package prc.autodoc;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import static prc.Main.err_pr;
|
||||
import static prc.autodoc.Main.*;
|
||||
|
||||
/**
|
||||
* This class handles generating
|
||||
*
|
||||
* @author Ornedan
|
||||
*/
|
||||
public class Icons {
|
||||
|
||||
/**
|
||||
* Visible from outside so that Main can wait on it.
|
||||
*/
|
||||
public static ExecutorService executor;
|
||||
//private static Timer timer;
|
||||
|
||||
private static boolean init = false;
|
||||
|
||||
private static HashSet<String> existingIcons = null;
|
||||
|
||||
private static HashMap<String, File> rawIcons = null;
|
||||
|
||||
private static void init() {
|
||||
/*try{
|
||||
reader = Jimi.createTypedJimiReader("image/targa");
|
||||
writer = Jimi.createTypedJimiWriter("image/png");
|
||||
}catch(JimiException e){
|
||||
err_pr.printException(e);
|
||||
icons = false;
|
||||
return;
|
||||
}*/
|
||||
init = true;
|
||||
existingIcons = new HashSet<String>();
|
||||
ImageIO.setUseCache(false);
|
||||
//executor = new ThreadPoolExecutor(50, 1000, 60, TimeUnit.SECONDS, bq);
|
||||
//timer = new Timer("Checker", true);
|
||||
executor = Executors.newCachedThreadPool();
|
||||
|
||||
rawIcons = new HashMap<String, File>();
|
||||
File[] tgas = new File("rawicons").listFiles(new FileFilter() {
|
||||
public boolean accept(File file) {
|
||||
return file.getName().toLowerCase().endsWith(".tga");
|
||||
}
|
||||
});
|
||||
|
||||
// Ensure the icons directory exists
|
||||
if (tgas == null) {
|
||||
err_pr.println("Error: Icons directory is missing!");
|
||||
if (tolErr) return;
|
||||
else System.exit(1);
|
||||
}
|
||||
|
||||
for (File tga : tgas)
|
||||
rawIcons.put(tga.getName().toLowerCase(), tga);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builds an <img>-tag pointing at a png-converted version of the
|
||||
* given icon.
|
||||
* If such an icon does not exist, returns a blank string.
|
||||
* The icon will be converted to PNG format if it has not yet been.
|
||||
*
|
||||
* @param iconName name of the icon to use
|
||||
* @return <img>-tag pointing at the image or a blank string
|
||||
*/
|
||||
public static String buildIcon(String iconName) {
|
||||
if (!icons) return "";
|
||||
else if (!init) init();
|
||||
|
||||
if (iconName.equals("****"))
|
||||
return "";
|
||||
|
||||
// Lowercase the name
|
||||
iconName = iconName.toLowerCase();
|
||||
|
||||
// Build the html
|
||||
String tag = iconTemplate.replace("~~~ImageURL~~~", "../../../images/" + iconName + ".png")
|
||||
.replace("~~~ImageName~~~", iconName);
|
||||
|
||||
// Case of already existing and indexed image
|
||||
if (existingIcons.contains(iconName))
|
||||
return tag;
|
||||
|
||||
File png = new File(imagePath + iconName + ".png");
|
||||
// See if the converted image exists already, but just hasn't been indexed yet
|
||||
if (png.exists()) {
|
||||
existingIcons.add(iconName);
|
||||
return tag;
|
||||
}
|
||||
|
||||
File tga = rawIcons.get(iconName + ".tga");
|
||||
// There is no icon to convert
|
||||
if (tga == null) {
|
||||
err_pr.println("Error: Missing icon file: " + iconName + ".tga");
|
||||
return "";
|
||||
}
|
||||
|
||||
// Schedule the conversion for execution
|
||||
Convert task = new Convert();
|
||||
task.init(tga, png);
|
||||
Future fut = executor.submit(task);
|
||||
|
||||
|
||||
// Schedule timer task
|
||||
/*
|
||||
Check check = new Check();
|
||||
check.init(fut, iconName);
|
||||
timer.schedule(check, System.currentTimeMillis() + 30000);
|
||||
*/
|
||||
/*
|
||||
try{
|
||||
reader.setSource(new FileInputStream(new File("rawicons" + fileSeparator + iconName + ".tga")));
|
||||
writer.setSource(reader.getImage());
|
||||
writer.putImage(imagePath + iconName + ".png");
|
||||
}catch(Exception e){
|
||||
err_pr.printException(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
*/
|
||||
// Assume eventual success and add the newly created image to the index
|
||||
existingIcons.add(iconName);
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
private static class Convert implements Runnable {
|
||||
private File inFile, outFile;
|
||||
|
||||
/**
|
||||
* Initialization method
|
||||
*
|
||||
* @param inFile input file, Targa format
|
||||
* @param outFile output file, Portable Network Graphics format
|
||||
*/
|
||||
public void init(File inFile, File outFile) {
|
||||
this.inFile = inFile;
|
||||
this.outFile = outFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Runnable#run()
|
||||
*/
|
||||
public void run() {
|
||||
try {
|
||||
if (!ImageIO.write(ImageIO.read(inFile), "png", outFile))
|
||||
err_pr.println("Error: Failed to convert image " + inFile);
|
||||
} catch (IOException e) {
|
||||
err_pr.printException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class Check extends TimerTask {
|
||||
private Future toCheck;
|
||||
private String iconName;
|
||||
|
||||
/**
|
||||
* Initialization method
|
||||
*
|
||||
* @param toCheck future representing the image conversion to check on
|
||||
* @param iconName name of the icon being converted by the task to check on
|
||||
*/
|
||||
public void init(Future toCheck, String iconName) {
|
||||
this.toCheck = toCheck;
|
||||
this.iconName = iconName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.TimerTask#run()
|
||||
*/
|
||||
public void run() {
|
||||
if (!toCheck.isDone()) {
|
||||
toCheck.cancel(true);
|
||||
err_pr.println("Error: Failed icon conversion on file " + iconName + ".tga");
|
||||
}
|
||||
|
||||
//executor.purge();
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
public static void main(String[] args) throws Exception{
|
||||
|
||||
System.out.println("Yar!");
|
||||
icons = true;
|
||||
iconTemplate = readTemplate("templates" + fileSeparator + "english" + fileSeparator + "icon.html");
|
||||
System.out.println(buildImg("test"));
|
||||
|
||||
ImageIO.setUseCache(false);
|
||||
Iterator<ImageReader> it = ImageIO.getImageReadersByMIMEType("image/targa");
|
||||
while(it.hasNext())
|
||||
System.out.println(it.next().getFormatName());
|
||||
|
||||
java.awt.image.BufferedImage buf = ImageIO.read(new File("isk_x1app.tga"));
|
||||
System.out.println("Tar!");
|
||||
ImageIO.write(buf, "png", new File("test.png"));
|
||||
System.out.println("Far!");
|
||||
|
||||
}
|
||||
*/
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main$Settings$Modes.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main$Settings$Modes.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main$Settings.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main$Settings.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main$SpellType.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main$SpellType.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main$TLKStore.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main$TLKStore.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main$TwoDAStore$Loader.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main$TwoDAStore$Loader.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main$TwoDAStore.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main$TwoDAStore.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main.class
Normal file
Binary file not shown.
984
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main.java
Normal file
984
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main.java
Normal file
@@ -0,0 +1,984 @@
|
||||
package prc.autodoc;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static prc.Main.*;
|
||||
import static prc.autodoc.EntryGeneration.*;
|
||||
import static prc.autodoc.MenuGeneration.*;
|
||||
import static prc.autodoc.PageGeneration.*;
|
||||
|
||||
/**
|
||||
* The main purpose of this autodocumenter is to create parts of the manual for
|
||||
* the PRC pack from 2da and TLK files. As a side effect of doing so, it finds
|
||||
* many errors present in the 2das.
|
||||
*/
|
||||
public class Main {
|
||||
/**
|
||||
* A small data structure class that gives access to both normal and custom
|
||||
* TLK with the same method
|
||||
*/
|
||||
public static class TLKStore {
|
||||
private final Data_TLK normal;
|
||||
private final Data_TLK custom;
|
||||
|
||||
/**
|
||||
* Creates a new TLKStore around the given two filenames. Equivalent to
|
||||
* TLKStore(normalName, customName, "tlk").
|
||||
*
|
||||
* @param normalName dialog.tlk or equivalent for the given language
|
||||
* @param customName prc_consortium.tlk or equivalent for the given languag
|
||||
* @throws TLKReadException if there are any problems reading either TLK
|
||||
*/
|
||||
public TLKStore(String normalName, String customName) {
|
||||
this.normal = new Data_TLK("tlk" + fileSeparator + normalName);
|
||||
this.custom = new Data_TLK("tlk" + fileSeparator + customName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new TLKStore around the given two filenames.
|
||||
*
|
||||
* @param normalName dialog.tlk or equivalent for the given language
|
||||
* @param customName prc_consortium.tlk or equivalent for the given languag
|
||||
* @param tlkDir Directory containing the two .tlk files
|
||||
* @throws TLKReadException if there are any problems reading either TLK
|
||||
*/
|
||||
public TLKStore(String normalName, String customName, String tlkDir) {
|
||||
this.normal = new Data_TLK(tlkDir + fileSeparator + normalName);
|
||||
this.custom = new Data_TLK(tlkDir + fileSeparator + customName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the TLK entry for the given StrRef. If there is nothing
|
||||
* at the location, returns Bad StrRef. Automatically picks between
|
||||
* normal and custom TLKs.
|
||||
*
|
||||
* @param num the line number in TLK
|
||||
* @return the contents of the given TLK slot, or Bad StrRef
|
||||
*/
|
||||
public String get(int num) {
|
||||
return num < 0x01000000 ? normal.getEntry(num) : custom.getEntry(num);
|
||||
}
|
||||
|
||||
/**
|
||||
* See above, except that this one automatically parses the string for
|
||||
* the number.
|
||||
*
|
||||
* @param num the line number in TLK as string
|
||||
* @return as above, except it returns Bad StrRef in case parsing failed
|
||||
*/
|
||||
public String get(String num) {
|
||||
try {
|
||||
return get(Integer.parseInt(num));
|
||||
} catch (NumberFormatException e) {
|
||||
return Main.badStrRef;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Another data structure class. Stores 2das and handles loading them.
|
||||
*/
|
||||
public static class TwoDAStore {
|
||||
private static class Loader implements Runnable {
|
||||
private final String pathToLoad;
|
||||
private final List<Data_2da> list;
|
||||
private final CountDownLatch latch;
|
||||
|
||||
/**
|
||||
* Creates a new Loader to load the given 2da file
|
||||
*
|
||||
* @param pathToLoad path of the 2da to load
|
||||
* @param list list to store the loaded data into
|
||||
* @param latch latch to countdown on once loading is complete
|
||||
*/
|
||||
public Loader(String pathToLoad, List<Data_2da> list, CountDownLatch latch) {
|
||||
this.pathToLoad = pathToLoad;
|
||||
this.list = list;
|
||||
this.latch = latch;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Runnable#run()
|
||||
*/
|
||||
public void run() {
|
||||
try {
|
||||
Data_2da data = Data_2da.load2da(pathToLoad, true);
|
||||
list.add(data);
|
||||
latch.countDown();
|
||||
} catch (Exception e) {
|
||||
err_pr.println("Error: Failure while reading main 2das. Exception data:\n");
|
||||
err_pr.printException(e);
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final HashMap<String, Data_2da> data = new HashMap<String, Data_2da>();
|
||||
private final String twoDAPath;
|
||||
|
||||
/**
|
||||
* Creates a new TwoDAStore, without preloading anything.
|
||||
*
|
||||
* @param twoDAPath Path of the directory containing 2da files.
|
||||
*/
|
||||
public TwoDAStore(String twoDAPath) {
|
||||
this.twoDAPath = twoDAPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a new TwoDAStore with all the main 2das preread in.
|
||||
* On a read failure, kills program execution, since there's nothing
|
||||
* that could be done anyway.
|
||||
*/
|
||||
public TwoDAStore() {
|
||||
this("2da");
|
||||
//long start = System.currentTimeMillis();
|
||||
if (verbose) System.out.print("Loading main 2da files ");
|
||||
boolean oldVerbose = verbose;
|
||||
verbose = false;
|
||||
|
||||
CountDownLatch latch = new CountDownLatch(7);
|
||||
List<Data_2da> list = Collections.synchronizedList(new ArrayList<Data_2da>());
|
||||
// Read the main 2das
|
||||
new Thread(new Loader("2da" + fileSeparator + "classes.2da", list, latch)).start();
|
||||
new Thread(new Loader("2da" + fileSeparator + "domains.2da", list, latch)).start();
|
||||
new Thread(new Loader("2da" + fileSeparator + "feat.2da", list, latch)).start();
|
||||
new Thread(new Loader("2da" + fileSeparator + "masterfeats.2da", list, latch)).start();
|
||||
new Thread(new Loader("2da" + fileSeparator + "racialtypes.2da", list, latch)).start();
|
||||
new Thread(new Loader("2da" + fileSeparator + "skills.2da", list, latch)).start();
|
||||
new Thread(new Loader("2da" + fileSeparator + "spells.2da", list, latch)).start();
|
||||
|
||||
try {
|
||||
latch.await();
|
||||
} catch (InterruptedException e) {
|
||||
err_pr.println("Error: Interrupted while reading main 2das. Exception data:\n");
|
||||
err_pr.printException(e);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
for (Data_2da entry : list)
|
||||
data.put(entry.getName(), entry);
|
||||
verbose = oldVerbose;
|
||||
if (verbose) System.out.println("- Done");
|
||||
/*
|
||||
try{
|
||||
data.put("classes", new Data_2da("2da" + fileSeparator + "classes.2da"));
|
||||
data.put("domains", new Data_2da("2da" + fileSeparator + "domains.2da"));
|
||||
data.put("feat", new Data_2da("2da" + fileSeparator + "feat.2da"));
|
||||
data.put("masterfeats", new Data_2da("2da" + fileSeparator + "masterfeats.2da"));
|
||||
data.put("racialtypes", new Data_2da("2da" + fileSeparator + "racialtypes.2da"));
|
||||
data.put("skills", new Data_2da("2da" + fileSeparator + "skills.2da"));
|
||||
data.put("spells", new Data_2da("2da" + fileSeparator + "spells.2da"));
|
||||
}catch(Exception e){
|
||||
err_pr.println("Error: Failure while reading main 2das. Exception data:\n");
|
||||
err_pr.printException(e);
|
||||
System.exit(1);
|
||||
}
|
||||
*/
|
||||
//System.out.println("Time taken: " + (System.currentTimeMillis() - start));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Data_2da structure wrapping the given 2da. If it hasn't been loaded
|
||||
* yet, the loading is done now.
|
||||
*
|
||||
* @param name name of the 2da to get. Without the file end ".2da".
|
||||
* @return a Data_2da structure
|
||||
* @throws TwoDAReadException if any errors are encountered while reading
|
||||
*/
|
||||
public Data_2da get(String name) {
|
||||
if (data.containsKey(name))
|
||||
return data.get(name);
|
||||
else {
|
||||
Data_2da temp = null;
|
||||
try {
|
||||
temp = Data_2da.load2da(twoDAPath + fileSeparator + name + ".2da", true);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new TwoDAReadException("Problem with filename when trying to read from 2da:\n" + e);
|
||||
}
|
||||
data.put(name, temp);
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class for handling the settings file.
|
||||
*/
|
||||
public static class Settings {
|
||||
/* Some pattern matchers for use when parsing the settings file */
|
||||
private final Matcher mainMatch = Pattern.compile("\\S+:").matcher("");
|
||||
private final Matcher paraMatch = Pattern.compile("\"[^\"]+\"").matcher("");
|
||||
private final Matcher langMatch = Pattern.compile("\\w+=\"[^\"]+\"").matcher("");
|
||||
|
||||
/* An enumeration of the possible setting types */
|
||||
private enum Modes {
|
||||
/**
|
||||
* The parser is currently working on lines specifying languages used.
|
||||
*/
|
||||
LANGUAGE,
|
||||
/**
|
||||
* The parser is currently working on lines containing string patterns that are
|
||||
* used in differentiating between entries in spells.2da.
|
||||
*/
|
||||
SIGNATURE,
|
||||
/**
|
||||
* The parser is currently working on lines listing spells.2da entries that contain
|
||||
* a significantly modified BW spell.
|
||||
*/
|
||||
MODIFIED_SPELL
|
||||
}
|
||||
|
||||
/* Settings data read in */
|
||||
/**
|
||||
* The settings for languages. An ArrayList of String[] containing setting for a specific language
|
||||
*/
|
||||
public ArrayList<String[]> languages = new ArrayList<String[]>();
|
||||
/**
|
||||
* An ArrayList of Integers. Indices to spells.2da of standard spells modified by the PRC
|
||||
*/
|
||||
public ArrayList<Integer> modifiedSpells = new ArrayList<Integer>();
|
||||
/**
|
||||
* A set of script name prefixes used to find epic spell entries in spells.2da
|
||||
*/
|
||||
public String[] epicspellSignatures = null;
|
||||
/*/** A set of script name prefixes used to find psionic power entries in spells.2da *
|
||||
public String[] psionicpowerSignatures = null;*/
|
||||
|
||||
/**
|
||||
* Read the settings file in and store the data for later access.
|
||||
* Terminates execution on any errors.
|
||||
*/
|
||||
public Settings() {
|
||||
try {
|
||||
// The settings file should be present in the directory this is run from
|
||||
Scanner reader = new Scanner(new File("settings"));
|
||||
String check;
|
||||
Modes mode = null;
|
||||
while (reader.hasNextLine()) {
|
||||
check = reader.nextLine();
|
||||
|
||||
// Skip comments and blank lines
|
||||
if (check.startsWith("#") || check.trim().equals("")) continue;
|
||||
|
||||
// Check if a new rule is starting
|
||||
mainMatch.reset(check);
|
||||
if (mainMatch.find()) {
|
||||
if (mainMatch.group().equals("language:")) mode = Modes.LANGUAGE;
|
||||
else if (mainMatch.group().equals("signature:")) mode = Modes.SIGNATURE;
|
||||
else if (mainMatch.group().equals("modified_spell:")) mode = Modes.MODIFIED_SPELL;
|
||||
else {
|
||||
throw new Exception("Unrecognized setting detected");
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Take action based on current mode
|
||||
if (mode == Modes.LANGUAGE) {
|
||||
String[] temp = new String[LANGDATA_NUMENTRIES];
|
||||
String result;
|
||||
langMatch.reset(check);
|
||||
// parse the language entry
|
||||
for (int i = 0; i < LANGDATA_NUMENTRIES; i++) {
|
||||
if (!langMatch.find())
|
||||
throw new Exception("Missing language parameter");
|
||||
result = langMatch.group();
|
||||
|
||||
if (result.startsWith("name=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_LANGNAME] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("base=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_BASETLK] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("prc=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_PRCTLK] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("feats=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_FEATSTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("allfeats=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_ALLFEATSTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("epicfeats=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_EPICFEATSTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("allepicfeats=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_ALLEPICFEATSTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("baseclasses=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_BASECLASSESTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("prestigeclasses=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_PRESTIGECLASSESTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("spells=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_SPELLSTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("epicspells=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_EPICSPELLSTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("psipowers=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_PSIONICPOWERSTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("modspells=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_MODIFIEDSPELLSTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("skills=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_SKILLSTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("domains=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_DOMAINSTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("races=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_RACESTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("spellbook=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_SPELLBOOKTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("powers=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_POWERTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("truenameutterances=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_TRUENAMEUTTERANCETXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("invocations=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_INVOCATIONTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("maneuvers=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_MANEUVERTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("utterances=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_UTTERANCETXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else
|
||||
throw new Exception("Unknown language parameter encountered\n" + check);
|
||||
}
|
||||
languages.add(temp);
|
||||
}
|
||||
// Parse the spell script name signatures
|
||||
if (mode == Modes.SIGNATURE) {
|
||||
String[] temp = check.trim().split("=");
|
||||
if (temp[0].equals("epicspell")) {
|
||||
epicspellSignatures = temp[1].replace("\"", "").split("\\|");
|
||||
}/* Not needed anymore
|
||||
else if(temp[0].equals("psionicpower")){
|
||||
psionicpowerSignatures = temp[1].replace("\"", "").split("\\|");
|
||||
}*/ else
|
||||
throw new Exception("Unknown signature parameter encountered:\n" + check);
|
||||
}
|
||||
// Parse the spell modified spell indices
|
||||
if (mode == Modes.MODIFIED_SPELL) {
|
||||
modifiedSpells.add(Integer.parseInt(check.trim()));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
err_pr.println("Error: Failed to read settings file:\n" + e + "\nAborting");
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A small enumeration for use in spell printing methods
|
||||
*/
|
||||
public enum SpellType {
|
||||
/**
|
||||
* The spell is not a real spell or psionic power, instead specifies some feat's spellscript.
|
||||
*/
|
||||
NONE,
|
||||
/**
|
||||
* The spell is a normal spell.
|
||||
*/
|
||||
NORMAL,
|
||||
/**
|
||||
* The spell is an epic spell.
|
||||
*/
|
||||
EPIC,
|
||||
/**
|
||||
* The spell is a psionic power.
|
||||
*/
|
||||
PSIONIC,
|
||||
/**
|
||||
* The spell is a truename utterance.
|
||||
*/
|
||||
UTTERANCE,
|
||||
/**
|
||||
* The spell is an invocation.
|
||||
*/
|
||||
INVOCATION,
|
||||
/**
|
||||
* The spell is a maneuver.
|
||||
*/
|
||||
MANEUVER
|
||||
}
|
||||
|
||||
/**
|
||||
* A switche determinining how errors are handled
|
||||
*/
|
||||
public static boolean tolErr = true;
|
||||
|
||||
/**
|
||||
* A boolean determining whether to print icons for the pages or not
|
||||
*/
|
||||
public static boolean icons = false;
|
||||
|
||||
/**
|
||||
* A constant signifying Bad StrRef
|
||||
*/
|
||||
public static final String badStrRef = "Bad StrRef";
|
||||
|
||||
/**
|
||||
* The container object for general configuration data read from file
|
||||
*/
|
||||
public static Settings settings;// = new Settings();
|
||||
|
||||
/**
|
||||
* The file separator, given it's own constant for ease of use
|
||||
*/
|
||||
public static final String fileSeparator = System.getProperty("file.separator");
|
||||
|
||||
/**
|
||||
* Array of the settings for currently used language. Index with the LANGDATA_ constants
|
||||
*/
|
||||
public static String[] curLanguageData = null;
|
||||
|
||||
/**
|
||||
* Size of the curLanguageData array
|
||||
*/
|
||||
public static final int LANGDATA_NUMENTRIES = 22;
|
||||
/**
|
||||
* curLanguageData index of the language name
|
||||
*/
|
||||
public static final int LANGDATA_LANGNAME = 0;
|
||||
/**
|
||||
* curLanguageData index of the name of the dialog.tlk equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_BASETLK = 1;
|
||||
/**
|
||||
* curLanguageData index of the name of the prc_consortium.tlk equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_PRCTLK = 2;
|
||||
/**
|
||||
* curLanguageData index of the name of the "All Feats" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_ALLFEATSTXT = 3;
|
||||
/**
|
||||
* curLanguageData index of the name of the "All Epic Feats" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_ALLEPICFEATSTXT = 4;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Feats" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_FEATSTXT = 5;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Epic Feats" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_EPICFEATSTXT = 6;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Base Classes" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_BASECLASSESTXT = 7;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Prestige Classes" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_PRESTIGECLASSESTXT = 8;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Spells" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_SPELLSTXT = 9;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Epic Spells" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_EPICSPELLSTXT = 10;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Psionic Powers" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_PSIONICPOWERSTXT = 11;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Modified Spells" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_MODIFIEDSPELLSTXT = 12;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Domains" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_DOMAINSTXT = 13;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Skills" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_SKILLSTXT = 14;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Races" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_RACESTXT = 15;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Spellbook" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_SPELLBOOKTXT = 16;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Powers" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_POWERTXT = 17;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Truename Utterances" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_TRUENAMEUTTERANCETXT = 18;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Invocations" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_INVOCATIONTXT = 19;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Maneuvers" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_MANEUVERTXT = 20;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Utterances" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_UTTERANCETXT = 21;
|
||||
|
||||
|
||||
/**
|
||||
* Current language name
|
||||
*/
|
||||
public static String curLanguage = null;
|
||||
|
||||
/**
|
||||
* The base path. <code>"manual" + fileSeparator + curLanguage + fileSeparator</code>
|
||||
*/
|
||||
public static String mainPath = null;
|
||||
/**
|
||||
* The path to content directory. <code>mainPath + "content" + fileSeparator</code>
|
||||
*/
|
||||
public static String contentPath = null;
|
||||
/**
|
||||
* The path to menu directory. <code>mainPath + "mainPath" + fileSeparator</code>
|
||||
*/
|
||||
public static String menuPath = null;
|
||||
/**
|
||||
* The path to the image directory. <code>"manual" + fileSeparator + "images" + fileSeparator</code>
|
||||
*/
|
||||
public static String imagePath = "manual" + fileSeparator + "images" + fileSeparator;
|
||||
|
||||
/**
|
||||
* Data structures for accessing TLKs
|
||||
*/
|
||||
public static TwoDAStore twoDA;
|
||||
/**
|
||||
* Data structures for accessing TLKs
|
||||
*/
|
||||
public static TLKStore tlk;
|
||||
|
||||
|
||||
/**
|
||||
* The template files
|
||||
*/
|
||||
public static String babAndSavthrTableHeaderTemplate = null,
|
||||
classTemplate = null,
|
||||
classTablesEntryTemplate = null,
|
||||
domainTemplate = null,
|
||||
featTemplate = null,
|
||||
mFeatTemplate = null,
|
||||
menuTemplate = null,
|
||||
menuItemTemplate = null,
|
||||
prereqANDFeatHeaderTemplate = null,
|
||||
prereqORFeatHeaderTemplate = null,
|
||||
raceTemplate = null,
|
||||
spellTemplate = null,
|
||||
skillTableHeaderTemplate = null,
|
||||
skillTemplate = null,
|
||||
successorFeatHeaderTemplate = null,
|
||||
iconTemplate = null,
|
||||
listEntrySetTemplate = null,
|
||||
listEntryTemplate = null,
|
||||
alphaSortedListTemplate = null,
|
||||
requiredForFeatHeaderTemplate = null,
|
||||
pageLinkTemplate = null,
|
||||
featMenuTemplate = null,
|
||||
spellSubradialListTemplate = null,
|
||||
spellSubradialListEntryTemplate = null,
|
||||
classFeatTableTemplate = null,
|
||||
classFeatTableEntryTemplate = null,
|
||||
classMagicTableTemplate = null,
|
||||
classMagicTableEntryTemplate = null,
|
||||
craftTemplate = null;
|
||||
|
||||
|
||||
/* Data structures to store generated entry data in */
|
||||
public static HashMap<Integer, SpellEntry> spells;
|
||||
public static HashMap<Integer, FeatEntry> masterFeats,
|
||||
feats;
|
||||
public static HashMap<Integer, ClassEntry> classes;
|
||||
public static HashMap<Integer, DomainEntry> domains;
|
||||
public static HashMap<Integer, RaceEntry> races;
|
||||
public static HashMap<Integer, GenericEntry> skills;
|
||||
|
||||
public static HashMap<Integer, GenericEntry> craft_armour;
|
||||
public static HashMap<Integer, GenericEntry> craft_weapon;
|
||||
public static HashMap<Integer, GenericEntry> craft_ring;
|
||||
public static HashMap<Integer, GenericEntry> craft_wondrous;
|
||||
|
||||
/**
|
||||
* Map of psionic power names to the indexes of the spells.2da entries chosen to represent the power in question
|
||||
*/
|
||||
public static HashMap<String, Integer> psiPowMap;
|
||||
|
||||
/**
|
||||
* Map of truenaming utterance names to the spells.2da indexes that contain utterance feat-linked entries
|
||||
*/
|
||||
public static HashMap<String, Integer> utterMap;
|
||||
|
||||
/**
|
||||
* Map of invocations to spells.2da
|
||||
*/
|
||||
public static HashMap<String, Integer> invMap;
|
||||
|
||||
/**
|
||||
* Map of maneuvers to spells.2da
|
||||
*/
|
||||
public static HashMap<String, Integer> maneuverMap;
|
||||
|
||||
|
||||
/**
|
||||
* Ye olde maine methode
|
||||
*
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
/* Argument parsing */
|
||||
for (String opt : args) {
|
||||
if (opt.equals("--help"))
|
||||
readMe();
|
||||
|
||||
if (opt.startsWith("-")) {
|
||||
if (opt.contains("a"))
|
||||
tolErr = true;
|
||||
if (opt.contains("q")) {
|
||||
verbose = false;
|
||||
spinner.disable();
|
||||
}
|
||||
if (opt.contains("i"))
|
||||
icons = true;
|
||||
if (opt.contains("s"))
|
||||
spinner.disable();
|
||||
if (opt.contains("?"))
|
||||
readMe();
|
||||
}
|
||||
}
|
||||
|
||||
// Load the settings
|
||||
settings = new Settings();
|
||||
|
||||
// Initialize the 2da container data structure
|
||||
twoDA = new TwoDAStore();
|
||||
|
||||
|
||||
// Print the manual files for each language specified
|
||||
for (int i = 0; i < settings.languages.size(); i++) {
|
||||
// Set language, path and load TLKs
|
||||
curLanguageData = settings.languages.get(i);
|
||||
curLanguage = curLanguageData[LANGDATA_LANGNAME];
|
||||
mainPath = "manual" + fileSeparator + curLanguage + fileSeparator;
|
||||
contentPath = mainPath + "content" + fileSeparator;
|
||||
menuPath = mainPath + "menus" + fileSeparator;
|
||||
|
||||
// If we fail on a language, skip to next one
|
||||
try {
|
||||
tlk = new TLKStore(curLanguageData[LANGDATA_BASETLK], curLanguageData[LANGDATA_PRCTLK]);
|
||||
} catch (TLKReadException e) {
|
||||
err_pr.println("Error: Failure while reading TLKs for language: " + curLanguage + ":\n" + e);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip to next if there is any problem with directories or templates
|
||||
if (!(readTemplates() && buildDirectories())) continue;
|
||||
|
||||
// Do the actual work
|
||||
createPages();
|
||||
createMenus();
|
||||
}
|
||||
|
||||
// Wait for the image conversion to finish before exiting main
|
||||
if (Icons.executor != null) {
|
||||
Icons.executor.shutdown();
|
||||
try {
|
||||
Icons.executor.awaitTermination(120, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
err_pr.println("Error: Interrupted while waiting for image conversion to finish");
|
||||
} finally {
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the use instructions for this program and kills execution.
|
||||
*/
|
||||
private static void readMe() {
|
||||
System.out.println("Usage:\n" +
|
||||
" java prc/autodoc/Main [--help][-aiqs?]\n" +
|
||||
"\n" +
|
||||
"-a forces aborting printing on errors\n" +
|
||||
"-i adds icons to pages\n" +
|
||||
"-q quiet mode. Does not print any progress info, only failure messages\n" +
|
||||
"-s disable the spinner. Useful when logging to file\n" +
|
||||
"\n" +
|
||||
"--help prints this info you are reading\n" +
|
||||
"-? see --help\n"
|
||||
);
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads all the template files for the current language.
|
||||
*
|
||||
* @return <code>true</code> if all the reads succeeded, <code>false</code> otherwise
|
||||
*/
|
||||
private static boolean readTemplates() {
|
||||
String templatePath = "templates" + fileSeparator + curLanguage + fileSeparator;
|
||||
|
||||
try {
|
||||
babAndSavthrTableHeaderTemplate = readTemplate(templatePath + "babNsavthrtableheader.html");
|
||||
classTablesEntryTemplate = readTemplate(templatePath + "classtablesentry.html");
|
||||
classTemplate = readTemplate(templatePath + "class.html");
|
||||
domainTemplate = readTemplate(templatePath + "domain.html");
|
||||
featTemplate = readTemplate(templatePath + "feat.html");
|
||||
mFeatTemplate = readTemplate(templatePath + "masterfeat.html");
|
||||
menuTemplate = readTemplate(templatePath + "menu.html");
|
||||
menuItemTemplate = readTemplate(templatePath + "menuitem.html");
|
||||
prereqANDFeatHeaderTemplate = readTemplate(templatePath + "prerequisiteandfeatheader.html");
|
||||
prereqORFeatHeaderTemplate = readTemplate(templatePath + "prerequisiteorfeatheader.html");
|
||||
raceTemplate = readTemplate(templatePath + "race.html");
|
||||
spellTemplate = readTemplate(templatePath + "spell.html");
|
||||
skillTableHeaderTemplate = readTemplate(templatePath + "skilltableheader.html");
|
||||
skillTemplate = readTemplate(templatePath + "skill.html");
|
||||
successorFeatHeaderTemplate = readTemplate(templatePath + "successorfeatheader.html");
|
||||
iconTemplate = readTemplate(templatePath + "icon.html");
|
||||
listEntrySetTemplate = readTemplate(templatePath + "listpageentryset.html");
|
||||
listEntryTemplate = readTemplate(templatePath + "listpageentry.html");
|
||||
alphaSortedListTemplate = readTemplate(templatePath + "alphasorted_listpage.html");
|
||||
requiredForFeatHeaderTemplate = readTemplate(templatePath + "reqforfeatheader.html");
|
||||
pageLinkTemplate = readTemplate(templatePath + "pagelink.html");
|
||||
featMenuTemplate = readTemplate(templatePath + "featmenu.html");
|
||||
spellSubradialListTemplate = readTemplate(templatePath + "spellsubradials.html");
|
||||
spellSubradialListEntryTemplate = readTemplate(templatePath + "spellsubradialsentry.html");
|
||||
classFeatTableTemplate = readTemplate(templatePath + "classfeattable.html");
|
||||
classFeatTableEntryTemplate = readTemplate(templatePath + "classfeattableentry.html");
|
||||
classMagicTableTemplate = readTemplate(templatePath + "classmagictable.html");
|
||||
classMagicTableEntryTemplate = readTemplate(templatePath + "classmagictableentry.html");
|
||||
craftTemplate = readTemplate(templatePath + "craftprop.html");
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the template file given as parameter and returns a string with it's contents
|
||||
* Kills execution if any operations fail.
|
||||
*
|
||||
* @param filePath string representing the path of the template file
|
||||
* @return the contents of the template file as a string
|
||||
* @throws IOException if the reading fails
|
||||
*/
|
||||
private static String readTemplate(String filePath) throws IOException {
|
||||
try {
|
||||
Scanner reader = new Scanner(new File(filePath));
|
||||
StringBuffer temp = new StringBuffer();
|
||||
|
||||
while (reader.hasNextLine()) temp.append(reader.nextLine() + "\n");
|
||||
|
||||
return temp.toString();
|
||||
} catch (Exception e) {
|
||||
err_pr.println("Error: Failed to read template file:\n" + e);
|
||||
throw new IOException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the directory structure for the current language
|
||||
* being processed.
|
||||
*
|
||||
* @return <code>true</code> if all directories are successfully created,
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
private static boolean buildDirectories() {
|
||||
String dirPath = mainPath + "content";
|
||||
|
||||
boolean toReturn = buildDir(dirPath);
|
||||
dirPath += fileSeparator;
|
||||
|
||||
toReturn = toReturn
|
||||
&& buildDir(dirPath + "base_classes")
|
||||
&& buildDir(dirPath + "class_epic_feats")
|
||||
&& buildDir(dirPath + "class_feats")
|
||||
&& buildDir(dirPath + "domains")
|
||||
&& buildDir(dirPath + "epic_feats")
|
||||
&& buildDir(dirPath + "epic_spells")
|
||||
&& buildDir(dirPath + "feats")
|
||||
&& buildDir(dirPath + "itemcrafting")
|
||||
&& buildDir(dirPath + "master_feats")
|
||||
&& buildDir(dirPath + "prestige_classes")
|
||||
&& buildDir(dirPath + "psionic_powers")
|
||||
&& buildDir(dirPath + "races")
|
||||
&& buildDir(dirPath + "skills")
|
||||
&& buildDir(dirPath + "spells")
|
||||
&& buildDir(dirPath + "utterances")
|
||||
&& buildDir(dirPath + "invocations")
|
||||
&& buildDir(dirPath + "maneuvers")
|
||||
|
||||
&& buildDir(mainPath + "menus");
|
||||
|
||||
System.gc();
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the actual work of building the directories
|
||||
*
|
||||
* @param path the target directory to create
|
||||
* @return <code>true</code> if the directory was already present or was successfully created,
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
private static boolean buildDir(String path) {
|
||||
File builder = new File(path);
|
||||
if (!builder.exists()) {
|
||||
if (!builder.mkdirs()) {
|
||||
err_pr.println("Error: Failure creating directory:\n" + builder.getPath());
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!builder.isDirectory()) {
|
||||
err_pr.println(builder.getPath() + " already exists as a file!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replaces each line break in the given TLK entry with
|
||||
* a line break followed by <code><br /></code>.
|
||||
*
|
||||
* @param toHTML tlk entry to convert
|
||||
* @return the modified string
|
||||
*/
|
||||
public static String htmlizeTLK(String toHTML) {
|
||||
return toHTML.replaceAll("\n", "\n<br />");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new file at the given <code>path</code>, erasing previous file if present.
|
||||
* Prints the given <code>content</code> string into the file.
|
||||
*
|
||||
* @param path the path of the file to be created
|
||||
* @param content the string to be printed into the file
|
||||
* @throws PageGenerationException if one of the file operations fails
|
||||
*/
|
||||
public static void printPage(String path, String content) {
|
||||
try {
|
||||
File target = new File(path);
|
||||
// Clean up old version if necessary
|
||||
if (target.exists()) {
|
||||
if (verbose) System.out.println("Deleting previous version of " + path);
|
||||
target.delete();
|
||||
}
|
||||
target.createNewFile();
|
||||
|
||||
// Creater the writer and print
|
||||
FileWriter writer = new FileWriter(target, false);
|
||||
writer.write(content);
|
||||
// Clean up
|
||||
writer.flush();
|
||||
writer.close();
|
||||
} catch (IOException e) {
|
||||
throw new PageGenerationException("IOException when printing " + path, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Page creation. Calls all the specific functions for different page types
|
||||
*/
|
||||
private static void createPages() {
|
||||
/* First, do the pages that do not require linking to other pages */
|
||||
doSkills();
|
||||
doCrafting();
|
||||
listPsionicPowers();
|
||||
listTruenameUtterances();
|
||||
listInvocations();
|
||||
listManeuvers();
|
||||
doSpells();
|
||||
|
||||
/* Then, build the feats */
|
||||
preliMasterFeats();
|
||||
preliFeats();
|
||||
linkFeats();
|
||||
|
||||
/* Last, domains, races and classes, which all link to the previous */
|
||||
doDomains();
|
||||
doRaces();
|
||||
doClasses();
|
||||
|
||||
/* Then, print all of it */
|
||||
printSkills();
|
||||
printSpells();
|
||||
printFeats();
|
||||
printDomains();
|
||||
printRaces();
|
||||
printClasses();
|
||||
printCrafting();
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu creation. Calls the specific functions for different menu types
|
||||
*/
|
||||
private static void createMenus() {
|
||||
/* First, the types that do not need any extra data beyond name & path
|
||||
* and use GenericEntry
|
||||
*/
|
||||
doGenericMenu(skills, curLanguageData[LANGDATA_SKILLSTXT], "manual_menus_skills.html");
|
||||
doGenericMenu(domains, curLanguageData[LANGDATA_DOMAINSTXT], "manual_menus_domains.html");
|
||||
doGenericMenu(races, curLanguageData[LANGDATA_RACESTXT], "manual_menus_races.html");
|
||||
doGenericMenu(craft_armour, curLanguageData[LANGDATA_SKILLSTXT], "manual_menus_craft_armour.html");
|
||||
doGenericMenu(craft_weapon, curLanguageData[LANGDATA_SKILLSTXT], "manual_menus_craft_weapon.html");
|
||||
doGenericMenu(craft_ring, curLanguageData[LANGDATA_SKILLSTXT], "manual_menus_craft_ring.html");
|
||||
doGenericMenu(craft_wondrous, curLanguageData[LANGDATA_SKILLSTXT], "manual_menus_craft_wondrous.html");
|
||||
/* Then the more specialised data where it needs to be split over several
|
||||
* menu pages
|
||||
*/
|
||||
doSpellMenus();
|
||||
doFeatMenus();
|
||||
doClassMenus();
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/MenuGeneration$1.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/MenuGeneration$1.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/MenuGeneration.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/MenuGeneration.class
Normal file
Binary file not shown.
263
nwn/nwnprc/DocGen/trunk/prc/autodoc/MenuGeneration.java
Normal file
263
nwn/nwnprc/DocGen/trunk/prc/autodoc/MenuGeneration.java
Normal file
@@ -0,0 +1,263 @@
|
||||
package prc.autodoc;
|
||||
|
||||
//import java.io.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import static prc.Main.verbose;
|
||||
import static prc.autodoc.Main.*;
|
||||
import static prc.autodoc.Main.SpellType.*;
|
||||
|
||||
public final class MenuGeneration {
|
||||
private MenuGeneration() {/* No instances */}
|
||||
|
||||
/**
|
||||
* Sorts any of the pages for which GenericEntry is enough into alphabetic order
|
||||
* using a TreeMap, and prints a menu page out of the results.
|
||||
*/
|
||||
public static void doGenericMenu(HashMap<Integer, ? extends GenericEntry> entries, String menuName, String menuFileName) {
|
||||
TreeMap<String, String> links = new TreeMap<String, String>();
|
||||
StringBuffer toPrint = new StringBuffer();
|
||||
|
||||
if (verbose) System.out.println("Printing menu for " + menuName);
|
||||
|
||||
for (GenericEntry entry : entries.values()) {
|
||||
links.put(entry.name, menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
entry.filePath.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", entry.name));
|
||||
}
|
||||
|
||||
while (links.size() > 0) {
|
||||
toPrint.append(links.remove(links.firstKey()));
|
||||
}
|
||||
|
||||
printPage(menuPath + menuFileName, menuTemplate.replaceAll("~~~menuName~~~", menuName)
|
||||
.replaceAll("~~~menuEntries~~~", toPrint.toString()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the spells into alphabetic order using a TreeMap, and prints a menu
|
||||
* page out of the results. Normal, epic and psionics get their own menus
|
||||
*/
|
||||
public static void doSpellMenus() {
|
||||
TreeMap<String, String> normalSpellLinks = new TreeMap<String, String>(),
|
||||
epicSpellLinks = new TreeMap<String, String>(),
|
||||
psionicPowerLinks = new TreeMap<String, String>(),
|
||||
utteranceLinks = new TreeMap<String, String>(),
|
||||
invocationLinks = new TreeMap<String, String>(),
|
||||
maneuverLinks = new TreeMap<String, String>(),
|
||||
modSpellLinks = new TreeMap<String, String>();
|
||||
StringBuffer normalPrint = new StringBuffer(),
|
||||
epicPrint = new StringBuffer(),
|
||||
psionicPrint = new StringBuffer(),
|
||||
utterancePrint = new StringBuffer(),
|
||||
invocationPrint = new StringBuffer(),
|
||||
maneuverPrint = new StringBuffer(),
|
||||
modSpellPrint = new StringBuffer();
|
||||
String temp = null;
|
||||
|
||||
if (verbose) System.out.println("Printing spell menus");
|
||||
|
||||
for (SpellEntry spell : spells.values()) {
|
||||
switch (spell.type) {
|
||||
case NORMAL:
|
||||
normalSpellLinks.put(spell.name, menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
spell.filePath.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", spell.name));
|
||||
break;
|
||||
case EPIC:
|
||||
temp = spell.name.startsWith("Epic Spell: ") ? spell.name.substring(12) : spell.name;
|
||||
epicSpellLinks.put(spell.name, menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
spell.filePath.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", temp));
|
||||
break;
|
||||
case PSIONIC:
|
||||
psionicPowerLinks.put(spell.name, menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
spell.filePath.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", spell.name));
|
||||
break;
|
||||
case UTTERANCE:
|
||||
utteranceLinks.put(spell.name, menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
spell.filePath.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", spell.name));
|
||||
break;
|
||||
case INVOCATION:
|
||||
invocationLinks.put(spell.name, menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
spell.filePath.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", spell.name));
|
||||
break;
|
||||
case MANEUVER:
|
||||
maneuverLinks.put(spell.name, menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
spell.filePath.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", spell.name));
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new AssertionError("Unhandled spelltype: " + spell.type);
|
||||
}
|
||||
|
||||
if (settings.modifiedSpells.contains(spell.entryNum))
|
||||
modSpellLinks.put(spell.name, menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
spell.filePath.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", spell.name));
|
||||
}
|
||||
|
||||
while (normalSpellLinks.size() > 0)
|
||||
normalPrint.append(normalSpellLinks.remove(normalSpellLinks.firstKey()));
|
||||
while (epicSpellLinks.size() > 0)
|
||||
epicPrint.append(epicSpellLinks.remove(epicSpellLinks.firstKey()));
|
||||
while (psionicPowerLinks.size() > 0)
|
||||
psionicPrint.append(psionicPowerLinks.remove(psionicPowerLinks.firstKey()));
|
||||
while (utteranceLinks.size() > 0)
|
||||
utterancePrint.append(utteranceLinks.remove(utteranceLinks.firstKey()));
|
||||
while (invocationLinks.size() > 0)
|
||||
invocationPrint.append(invocationLinks.remove(invocationLinks.firstKey()));
|
||||
while (maneuverLinks.size() > 0)
|
||||
maneuverPrint.append(maneuverLinks.remove(maneuverLinks.firstKey()));
|
||||
while (modSpellLinks.size() > 0)
|
||||
modSpellPrint.append(modSpellLinks.remove(modSpellLinks.firstKey()));
|
||||
|
||||
printPage(menuPath + "manual_menus_spells.html", menuTemplate.replaceAll("~~~menuName~~~", curLanguageData[LANGDATA_SPELLSTXT])
|
||||
.replaceAll("~~~menuEntries~~~", normalPrint.toString()));
|
||||
printPage(menuPath + "manual_menus_epic_spells.html", menuTemplate.replaceAll("~~~menuName~~~", curLanguageData[LANGDATA_EPICSPELLSTXT])
|
||||
.replaceAll("~~~menuEntries~~~", epicPrint.toString()));
|
||||
printPage(menuPath + "manual_menus_psionic_powers.html", menuTemplate.replaceAll("~~~menuName~~~", curLanguageData[LANGDATA_PSIONICPOWERSTXT])
|
||||
.replaceAll("~~~menuEntries~~~", psionicPrint.toString()));
|
||||
printPage(menuPath + "manual_menus_truename_utterances.html", menuTemplate.replaceAll("~~~menuName~~~", curLanguageData[LANGDATA_TRUENAMEUTTERANCETXT])
|
||||
.replaceAll("~~~menuEntries~~~", utterancePrint.toString()));
|
||||
printPage(menuPath + "manual_menus_invocations.html", menuTemplate.replaceAll("~~~menuName~~~", curLanguageData[LANGDATA_INVOCATIONTXT])
|
||||
.replaceAll("~~~menuEntries~~~", invocationPrint.toString()));
|
||||
printPage(menuPath + "manual_menus_maneuvers.html", menuTemplate.replaceAll("~~~menuName~~~", curLanguageData[LANGDATA_MANEUVERTXT])
|
||||
.replaceAll("~~~menuEntries~~~", maneuverPrint.toString()));
|
||||
printPage(menuPath + "manual_menus_modified_spells.html", menuTemplate.replaceAll("~~~menuName~~~", curLanguageData[LANGDATA_MODIFIEDSPELLSTXT])
|
||||
.replaceAll("~~~menuEntries~~~", modSpellPrint.toString()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sorts the feats into alphabetic order using a TreeMap, and prints a menu
|
||||
* page out of the results. Normal and epic feats get their own menus and class feats
|
||||
* are skipped.
|
||||
*/
|
||||
public static void doFeatMenus() {
|
||||
TreeMap<String, String> normalFeatLinks = new TreeMap<String, String>(),
|
||||
normalMasterfeatLinks = new TreeMap<String, String>(),
|
||||
epicFeatLinks = new TreeMap<String, String>(),
|
||||
epicMasterfeatLinks = new TreeMap<String, String>();
|
||||
StringBuffer normalList = new StringBuffer(),
|
||||
normalMasterList = new StringBuffer(),
|
||||
epicList = new StringBuffer(),
|
||||
epicMasterList = new StringBuffer();
|
||||
String temp = null;
|
||||
String normalMenu = featMenuTemplate,
|
||||
epicMenu = featMenuTemplate;
|
||||
|
||||
if (verbose) System.out.println("Printing feat menus");
|
||||
|
||||
// Print names
|
||||
normalMenu = normalMenu.replaceAll("~~~menuName~~~", curLanguageData[LANGDATA_FEATSTXT]);
|
||||
epicMenu = epicMenu.replaceAll("~~~menuName~~~", curLanguageData[LANGDATA_EPICFEATSTXT]);
|
||||
|
||||
// Parse through feats
|
||||
for (FeatEntry feat : feats.values()) {
|
||||
// Skip class feats and feats with masterfeat or a predecessor
|
||||
if (feat.isClassFeat || feat.isSuccessor || feat.master != null) continue;
|
||||
if (!feat.isEpic)
|
||||
normalFeatLinks.put(feat.name, menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
feat.filePath.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", feat.name));
|
||||
else
|
||||
epicFeatLinks.put(feat.name, menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
feat.filePath.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", feat.name));
|
||||
}
|
||||
|
||||
// Transfer the feat link lists into text form
|
||||
while (normalFeatLinks.size() > 0)
|
||||
normalList.append(normalFeatLinks.remove(normalFeatLinks.firstKey()));
|
||||
while (epicFeatLinks.size() > 0)
|
||||
epicList.append(epicFeatLinks.remove(epicFeatLinks.firstKey()));
|
||||
|
||||
// Parse through masterfeats
|
||||
for (FeatEntry masterfeat : masterFeats.values()) {
|
||||
if (masterfeat.isClassFeat && masterfeat.allChildrenClassFeat) continue;
|
||||
if (masterfeat.isEpic)
|
||||
epicMasterfeatLinks.put(masterfeat.name, menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
masterfeat.filePath.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", masterfeat.name));
|
||||
if (!masterfeat.allChildrenEpic)
|
||||
normalMasterfeatLinks.put(masterfeat.name, menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
masterfeat.filePath.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", masterfeat.name));
|
||||
}
|
||||
|
||||
// Transfer the masterfeat link lists into text form
|
||||
while (normalMasterfeatLinks.size() > 0)
|
||||
normalMasterList.append(normalMasterfeatLinks.remove(normalMasterfeatLinks.firstKey()));
|
||||
while (epicMasterfeatLinks.size() > 0)
|
||||
epicMasterList.append(epicMasterfeatLinks.remove(epicMasterfeatLinks.firstKey()));
|
||||
|
||||
// Add in a link to the page listing *all* feats
|
||||
normalMenu = normalMenu.replaceAll("~~~allFeatsLink~~~", menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
(contentPath + "feats" + fileSeparator + "alphasortedfeats.html")
|
||||
.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", curLanguageData[LANGDATA_ALLFEATSTXT]));
|
||||
|
||||
// Add in a link to the page listing all epic feats
|
||||
epicMenu = epicMenu.replaceAll("~~~allFeatsLink~~~", menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
(contentPath + "epic_feats" + fileSeparator + "alphasortedepicfeats.html")
|
||||
.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", curLanguageData[LANGDATA_ALLEPICFEATSTXT]));
|
||||
|
||||
// Add in the masterfeat links
|
||||
normalMenu = normalMenu.replaceAll("~~~masterFeats~~~", normalMasterList.toString());
|
||||
epicMenu = epicMenu.replaceAll("~~~masterFeats~~~", epicMasterList.toString());
|
||||
|
||||
// Add in the feat links
|
||||
normalMenu = normalMenu.replaceAll("~~~featLinks~~~", normalList.toString());
|
||||
epicMenu = epicMenu.replaceAll("~~~featLinks~~~", epicList.toString());
|
||||
|
||||
// Print the pages
|
||||
printPage(menuPath + "manual_menus_feat.html", normalMenu);
|
||||
printPage(menuPath + "manual_menus_epic_feat.html", epicMenu);
|
||||
}
|
||||
|
||||
//private static void doFeatMenusAux()
|
||||
|
||||
|
||||
/**
|
||||
* Sorts the classes into alphabetic order using a TreeMap, and prints a menu
|
||||
* page out of the results. Base and prestige classes get their own menus
|
||||
*/
|
||||
public static void doClassMenus() {
|
||||
TreeMap<String, String> baseLinks = new TreeMap<String, String>(),
|
||||
prestigeLinks = new TreeMap<String, String>();
|
||||
StringBuffer basePrint = new StringBuffer(),
|
||||
prestigePrint = new StringBuffer();
|
||||
String temp = null;
|
||||
|
||||
if (verbose) System.out.println("Printing class menus");
|
||||
|
||||
for (ClassEntry clazz : classes.values()) {
|
||||
if (clazz.isBase)
|
||||
baseLinks.put(clazz.name, menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
clazz.filePath.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", clazz.name));
|
||||
else
|
||||
prestigeLinks.put(clazz.name, menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
clazz.filePath.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", clazz.name));
|
||||
}
|
||||
|
||||
while (baseLinks.size() > 0)
|
||||
basePrint.append(baseLinks.remove(baseLinks.firstKey()));
|
||||
while (prestigeLinks.size() > 0)
|
||||
prestigePrint.append(prestigeLinks.remove(prestigeLinks.firstKey()));
|
||||
|
||||
printPage(menuPath + "manual_menus_base_classes.html", menuTemplate.replaceAll("~~~menuName~~~", curLanguageData[LANGDATA_BASECLASSESTXT])
|
||||
.replaceAll("~~~menuEntries~~~", basePrint.toString()));
|
||||
printPage(menuPath + "manual_menus_prestige_classes.html", menuTemplate.replaceAll("~~~menuName~~~", curLanguageData[LANGDATA_PRESTIGECLASSESTXT])
|
||||
.replaceAll("~~~menuEntries~~~", prestigePrint.toString()));
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/PageGeneration.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/PageGeneration.class
Normal file
Binary file not shown.
602
nwn/nwnprc/DocGen/trunk/prc/autodoc/PageGeneration.java
Normal file
602
nwn/nwnprc/DocGen/trunk/prc/autodoc/PageGeneration.java
Normal file
@@ -0,0 +1,602 @@
|
||||
package prc.autodoc;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import static prc.Main.err_pr;
|
||||
import static prc.Main.verbose;
|
||||
import static prc.autodoc.Main.*;
|
||||
|
||||
/**
|
||||
* This class contains the methods for manual page generation.
|
||||
*
|
||||
* @author Ornedan
|
||||
*/
|
||||
public final class PageGeneration {
|
||||
private PageGeneration() {/* No need for instantiation */}
|
||||
|
||||
/**
|
||||
* Handles printing of the skill pages.
|
||||
*/
|
||||
public static void printSkills() {
|
||||
String text = null;
|
||||
|
||||
for (GenericEntry skill : skills.values()) {
|
||||
if (verbose) System.out.println("Printing page for " + skill.name);
|
||||
// Start building the entry data. First, place in the name
|
||||
text = skillTemplate;
|
||||
text = text.replaceAll("~~~SkillName~~~", skill.name);
|
||||
// Then, put in the description
|
||||
text = text.replaceAll("~~~SkillTLKDescription~~~",
|
||||
skill.text);
|
||||
// Add in the icon
|
||||
text = text.replaceAll("~~~Icon~~~", skill.iconPath);
|
||||
|
||||
// Print the page
|
||||
try {
|
||||
printPage(skill.filePath, text);
|
||||
} catch (PageGenerationException e) {
|
||||
err_pr.println("Error: Exception when writing page for skill " + skill.entryNum + ": " + skill.name + ":\n" + e);
|
||||
}
|
||||
}
|
||||
System.gc();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles printing of the crafting property pages.
|
||||
*/
|
||||
public static void printCrafting() {
|
||||
String text = null;
|
||||
|
||||
for (GenericEntry craft_armour_var : craft_armour.values()) {
|
||||
if (verbose) System.out.println("Printing page for " + craft_armour_var.name);
|
||||
// Start building the entry data. First, place in the name
|
||||
text = craftTemplate;
|
||||
text = text.replaceAll("~~~CraftPropName~~~", craft_armour_var.name);
|
||||
// Then, put in the description
|
||||
text = text.replaceAll("~~~CraftPropTLKDescription~~~",
|
||||
craft_armour_var.text);
|
||||
// Print the page
|
||||
try {
|
||||
printPage(craft_armour_var.filePath, text);
|
||||
} catch (PageGenerationException e) {
|
||||
err_pr.println("Error: Exception when writing page for skill " + craft_armour_var.entryNum + ": " + craft_armour_var.name + ":\n" + e);
|
||||
}
|
||||
}
|
||||
for (GenericEntry craft_weapon_var : craft_weapon.values()) {
|
||||
if (verbose) System.out.println("Printing page for " + craft_weapon_var.name);
|
||||
// Start building the entry data. First, place in the name
|
||||
text = craftTemplate;
|
||||
text = text.replaceAll("~~~CraftPropName~~~", craft_weapon_var.name);
|
||||
// Then, put in the description
|
||||
text = text.replaceAll("~~~CraftPropTLKDescription~~~",
|
||||
craft_weapon_var.text);
|
||||
// Print the page
|
||||
try {
|
||||
printPage(craft_weapon_var.filePath, text);
|
||||
} catch (PageGenerationException e) {
|
||||
err_pr.println("Error: Exception when writing page for skill " + craft_weapon_var.entryNum + ": " + craft_weapon_var.name + ":\n" + e);
|
||||
}
|
||||
}
|
||||
for (GenericEntry craft_ring_var : craft_ring.values()) {
|
||||
if (verbose) System.out.println("Printing page for " + craft_ring_var.name);
|
||||
// Start building the entry data. First, place in the name
|
||||
text = craftTemplate;
|
||||
text = text.replaceAll("~~~CraftPropName~~~", craft_ring_var.name);
|
||||
// Then, put in the description
|
||||
text = text.replaceAll("~~~CraftPropTLKDescription~~~",
|
||||
craft_ring_var.text);
|
||||
// Print the page
|
||||
try {
|
||||
printPage(craft_ring_var.filePath, text);
|
||||
} catch (PageGenerationException e) {
|
||||
err_pr.println("Error: Exception when writing page for skill " + craft_ring_var.entryNum + ": " + craft_ring_var.name + ":\n" + e);
|
||||
}
|
||||
}
|
||||
for (GenericEntry craft_wondrous_var : craft_wondrous.values()) {
|
||||
if (verbose) System.out.println("Printing page for " + craft_wondrous_var.name);
|
||||
// Start building the entry data. First, place in the name
|
||||
text = craftTemplate;
|
||||
text = text.replaceAll("~~~CraftPropName~~~", craft_wondrous_var.name);
|
||||
// Then, put in the description
|
||||
text = text.replaceAll("~~~CraftPropTLKDescription~~~",
|
||||
craft_wondrous_var.text);
|
||||
// Print the page
|
||||
try {
|
||||
printPage(craft_wondrous_var.filePath, text);
|
||||
} catch (PageGenerationException e) {
|
||||
err_pr.println("Error: Exception when writing page for skill " + craft_wondrous_var.entryNum + ": " + craft_wondrous_var.name + ":\n" + e);
|
||||
}
|
||||
}
|
||||
System.gc();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prints all spells and spell-likes (psionics, truenaming).
|
||||
* As of now, all of these are similar enough to share the same
|
||||
* template, so they can be done here together.
|
||||
*/
|
||||
public static void printSpells() {
|
||||
String text = null;
|
||||
StringBuilder subradialText = null;
|
||||
|
||||
for (SpellEntry spell : spells.values()) {
|
||||
if (verbose) System.out.println("Printing page for " + spell.name);
|
||||
// Start building the entry data. First, place in the name
|
||||
text = spellTemplate;
|
||||
text = text.replaceAll("~~~SpellName~~~", spell.name);
|
||||
// Then, put in the description
|
||||
text = text.replaceAll("~~~SpellTLKDescription~~~",
|
||||
spell.text);
|
||||
// Add in the icon
|
||||
text = text.replaceAll("~~~Icon~~~", spell.iconPath);
|
||||
|
||||
// Handle subradials, if any
|
||||
subradialText = new StringBuilder();
|
||||
if (spell.subradials != null) {
|
||||
for (Tuple<String, String> subradial : spell.subradials) {
|
||||
subradialText.append(spellSubradialListEntryTemplate.replaceAll("~~~Icon~~~", subradial.e2)
|
||||
.replaceAll("~~~SubradialName~~~", subradial.e1));
|
||||
}
|
||||
subradialText = new StringBuilder(spellSubradialListTemplate.replaceAll("~~~EntryList~~~", subradialText.toString()));
|
||||
}
|
||||
text = text.replaceAll("~~~SubradialNames~~~", subradialText.toString());
|
||||
|
||||
// Print the page
|
||||
try {
|
||||
printPage(spell.filePath, text);
|
||||
} catch (PageGenerationException e) {
|
||||
err_pr.println("Error: Exception when writing page for spell " + spell.entryNum + ": " + spell.name + ":\n" + e);
|
||||
}
|
||||
}
|
||||
// Force a clean-up of dead objects. This will keep discarded objects from slowing down the program as it
|
||||
// hits the memory limit
|
||||
System.gc();
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple method for printing out all the feat pages.
|
||||
*/
|
||||
public static void printFeats() {
|
||||
// Print feats
|
||||
printFeatsAux();
|
||||
|
||||
// Print masterfeats
|
||||
printMasterFeatsAux();
|
||||
|
||||
// Print a page with alphabetically sorted list of all feats
|
||||
printPage(contentPath + "feats" + fileSeparator + "alphasortedfeats.html", buildAllFeatsList(false));
|
||||
|
||||
// Print a page with alphabetically sorted list of all epic feats
|
||||
printPage(contentPath + "epic_feats" + fileSeparator + "alphasortedepicfeats.html", buildAllFeatsList(true));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prints the masterfeat pages.
|
||||
*/
|
||||
private static void printMasterFeatsAux() {
|
||||
String text = null,
|
||||
temp = null;
|
||||
|
||||
for (FeatEntry masterfeat : masterFeats.values()) {
|
||||
if (verbose) System.out.println("Printing page for " + masterfeat.name);
|
||||
// Build the entry data
|
||||
text = mFeatTemplate;
|
||||
text = text.replaceAll("~~~FeatName~~~",
|
||||
masterfeat.name);
|
||||
text = text.replaceAll("~~~FeatTLKDescription~~~",
|
||||
masterfeat.text);
|
||||
// Add in the icon
|
||||
text = text.replaceAll("~~~Icon~~~", masterfeat.iconPath);
|
||||
|
||||
// Add in child feats
|
||||
temp = "";
|
||||
for (FeatEntry child : masterfeat.childFeats.values()) {
|
||||
temp += pageLinkTemplate.replace("~~~Path~~~", child.filePath.replace(contentPath, "../").replaceAll("\\\\", "/"))
|
||||
.replace("~~~Name~~~", child.name);
|
||||
}
|
||||
text = text.replaceAll("~~~MasterFeatChildList~~~", temp);
|
||||
|
||||
// Print the page
|
||||
try {
|
||||
printPage(masterfeat.filePath, text);
|
||||
} catch (PageGenerationException e) {
|
||||
err_pr.println("Error: Exception when writing page for masterfeat " + masterfeat.entryNum + ": " + masterfeat.name + ":\n" + e);
|
||||
}
|
||||
}
|
||||
System.gc();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prints the feat pages.
|
||||
*/
|
||||
private static void printFeatsAux() {
|
||||
String text = null,
|
||||
temp = null;
|
||||
StringBuilder subradialText = null;
|
||||
|
||||
for (FeatEntry feat : feats.values()) {
|
||||
if (verbose) System.out.println("Printing page for " + feat.name);
|
||||
// Build the entry data
|
||||
text = featTemplate;
|
||||
text = text.replaceAll("~~~FeatName~~~",
|
||||
feat.name);
|
||||
text = text.replaceAll("~~~FeatTLKDescription~~~",
|
||||
feat.text);
|
||||
// Add in the icon
|
||||
text = text.replaceAll("~~~Icon~~~", feat.iconPath);
|
||||
|
||||
// Print prerequisites into the entry
|
||||
temp = "";
|
||||
if (feat.andRequirements.size() != 0) {
|
||||
temp += prereqANDFeatHeaderTemplate;
|
||||
for (FeatEntry andReq : feat.andRequirements.values())
|
||||
temp += pageLinkTemplate.replace("~~~Path~~~", andReq.filePath.replace(contentPath, "../").replaceAll("\\\\", "/"))
|
||||
.replace("~~~Name~~~", andReq.name);
|
||||
}
|
||||
if (feat.orRequirements.size() != 0) {
|
||||
temp += prereqORFeatHeaderTemplate;
|
||||
for (FeatEntry orReq : feat.orRequirements.values())
|
||||
temp += pageLinkTemplate.replace("~~~Path~~~", orReq.filePath.replace(contentPath, "../").replaceAll("\\\\", "/"))
|
||||
.replace("~~~Name~~~", orReq.name);
|
||||
}
|
||||
text = text.replaceAll("~~~PrerequisiteFeatList~~~", temp);
|
||||
|
||||
// Print the successor, if any, into the entry
|
||||
temp = "";
|
||||
if (feat.successor != null) {
|
||||
temp += successorFeatHeaderTemplate + pageLinkTemplate.replace("~~~Path~~~", feat.successor.filePath.replace(contentPath, "../").replaceAll("\\\\", "/"))
|
||||
.replace("~~~Name~~~", feat.successor.name);
|
||||
}
|
||||
text = text.replaceAll("~~~SuccessorFeat~~~", temp);
|
||||
|
||||
// Handle subradials, if any
|
||||
subradialText = new StringBuilder();
|
||||
if (feat.subradials != null) {
|
||||
for (Tuple<String, String> subradial : feat.subradials) {
|
||||
subradialText.append(spellSubradialListEntryTemplate.replaceAll("~~~Icon~~~", subradial.e2)
|
||||
.replaceAll("~~~SubradialName~~~", subradial.e1));
|
||||
}
|
||||
subradialText = new StringBuilder(spellSubradialListTemplate.replaceAll("~~~EntryList~~~", subradialText.toString()));
|
||||
}
|
||||
text = text.replaceAll("~~~SubradialNames~~~", subradialText.toString());
|
||||
|
||||
// Handle feats that have this as their prerequisite
|
||||
temp = "";
|
||||
if (feat.requiredForFeats.size() != 0) {
|
||||
temp += requiredForFeatHeaderTemplate;
|
||||
for (FeatEntry req : feat.requiredForFeats.values()) {
|
||||
temp += pageLinkTemplate.replace("~~~Path~~~", req.filePath.replace(contentPath, "../").replaceAll("\\\\", "/"))
|
||||
.replace("~~~Name~~~", req.name);
|
||||
}
|
||||
}
|
||||
text = text.replaceAll("~~~RequiredForFeatList~~~", temp);
|
||||
|
||||
// Print the page
|
||||
try {
|
||||
printPage(feat.filePath, text);
|
||||
} catch (PageGenerationException e) {
|
||||
err_pr.println("Error: Exception when writing page for feat " + feat.entryNum + ": " + feat.name + ":\n" + e);
|
||||
}
|
||||
}
|
||||
System.gc();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs an alphabetically sorted list of all (or only all epic) feats.
|
||||
*
|
||||
* @param epicOnly if <code>true</code>, only feats that are epic are placed in the list. Otherwise, all feats.
|
||||
* @return an html page containing the list
|
||||
*/
|
||||
private static String buildAllFeatsList(boolean epicOnly) {
|
||||
TreeMap<String, FeatEntry> sorted = new TreeMap<String, FeatEntry>(String.CASE_INSENSITIVE_ORDER);
|
||||
for (FeatEntry entry : feats.values())
|
||||
if (!epicOnly || (epicOnly && entry.isEpic))
|
||||
sorted.put(entry.name, entry);
|
||||
String toReturn = alphaSortedListTemplate,
|
||||
entrySet;
|
||||
FeatEntry entry;
|
||||
char cha = (char) 0;
|
||||
int counter = 0;
|
||||
boolean addedAny;
|
||||
while (sorted.size() > 0) {
|
||||
// Build the list for a single letter
|
||||
entrySet = listEntrySetTemplate.replace("~~~LinkId~~~", new String(new char[]{cha}))
|
||||
.replace("~~~EntrySetName~~~", new String(new char[]{cha}).toUpperCase());
|
||||
addedAny = false;
|
||||
while (sorted.size() > 0 &&
|
||||
sorted.firstKey().toLowerCase().startsWith(new String(new char[]{cha}))) {
|
||||
addedAny = true;
|
||||
entry = sorted.remove(sorted.firstKey());
|
||||
|
||||
entrySet = entrySet.replace("~~~FeatList~~~", listEntryTemplate.replace("~~~EvenOrOdd~~~", (counter++ % 2) == 0 ? "even" : "odd")
|
||||
.replace("~~~EntryPath~~~",
|
||||
entry.filePath.replace(contentPath, "../").replaceAll("\\\\", "/"))
|
||||
.replace("~~~EntryName~~~", entry.name)
|
||||
+ "~~~FeatList~~~");
|
||||
}
|
||||
entrySet = entrySet.replace("~~~FeatList~~~", "");
|
||||
cha++;
|
||||
|
||||
// Add the sublist to the page
|
||||
if (addedAny)
|
||||
toReturn = toReturn.replace("~~~Content~~~", entrySet + "\n" + "~~~Content~~~");
|
||||
}
|
||||
// Clear off the last replacement marker
|
||||
toReturn = toReturn.replace("~~~Content~~~", "");
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handles creation of the domain pages.
|
||||
*/
|
||||
public static void printDomains() {
|
||||
String text = null;
|
||||
StringBuffer spellList = null;
|
||||
|
||||
for (DomainEntry domain : domains.values()) {
|
||||
if (verbose) System.out.println("Printing page for " + domain.name);
|
||||
// Build the entry data
|
||||
text = domainTemplate;
|
||||
text = text.replaceAll("~~~DomainName~~~",
|
||||
domain.name);
|
||||
text = text.replaceAll("~~~DomainTLKDescription~~~",
|
||||
domain.text);
|
||||
// Add in the icon
|
||||
text = text.replaceAll("~~~Icon~~~", domain.iconPath);
|
||||
|
||||
// Add a link to the granted feat
|
||||
text = text.replaceAll("~~~DomainFeat~~~",
|
||||
pageLinkTemplate.replace("~~~Path~~~", domain.grantedFeat.filePath.replace(contentPath, "../").replaceAll("\\\\", "/"))
|
||||
.replace("~~~Name~~~", domain.grantedFeat.name));
|
||||
|
||||
// Add links to the granted spells
|
||||
spellList = new StringBuffer();
|
||||
for (SpellEntry grantedSpell : domain.spells) {
|
||||
spellList.append(pageLinkTemplate.replace("~~~Path~~~", grantedSpell.filePath.replace(contentPath, "../").replaceAll("\\\\", "/"))
|
||||
.replace("~~~Name~~~", grantedSpell.name));
|
||||
}
|
||||
text = text.replaceAll("~~~DomainSpellList~~~", spellList.toString());
|
||||
|
||||
// Print the page
|
||||
try {
|
||||
printPage(domain.filePath, text);
|
||||
} catch (PageGenerationException e) {
|
||||
err_pr.println("Error: Exception when writing page for domain " + domain.entryNum + ": " + domain.name + ":\n" + e);
|
||||
}
|
||||
}
|
||||
System.gc();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handles creation of the race pages.
|
||||
*/
|
||||
public static void printRaces() {
|
||||
String text = null;
|
||||
StringBuffer featList = null;
|
||||
|
||||
for (RaceEntry race : races.values()) {
|
||||
if (verbose) System.out.println("Printing page for " + race.name);
|
||||
// Build the entry data
|
||||
text = raceTemplate;
|
||||
text = text.replaceAll("~~~RaceName~~~",
|
||||
race.name);
|
||||
text = text.replaceAll("~~~RaceTLKDescription~~~",
|
||||
race.text);
|
||||
|
||||
// Add links to the racial feats
|
||||
featList = new StringBuffer();
|
||||
for (FeatEntry grantedFeat : race.raceFeats.values()) {
|
||||
featList.append(pageLinkTemplate.replace("~~~Path~~~", grantedFeat.filePath.replace(contentPath, "../").replaceAll("\\\\", "/"))
|
||||
.replace("~~~Name~~~", grantedFeat.name));
|
||||
}
|
||||
text = text.replaceAll("~~~RaceFeats~~~", featList.toString());
|
||||
|
||||
// Print the page
|
||||
try {
|
||||
printPage(race.filePath, text);
|
||||
} catch (PageGenerationException e) {
|
||||
err_pr.println("Error: Exception when writing page for race " + race.entryNum + ": " + race.name + ":\n" + e);
|
||||
}
|
||||
}
|
||||
System.gc();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handles creation of the class pages.
|
||||
* Subsections handled by several following methods.
|
||||
*/
|
||||
public static void printClasses() {
|
||||
String text = null,
|
||||
temp = null;
|
||||
String[] tempArr = null;
|
||||
|
||||
for (ClassEntry class_ : classes.values()) {
|
||||
if (verbose) System.out.println("Printing page for " + class_.name);
|
||||
// Build the entry data
|
||||
text = classTemplate;
|
||||
text = text.replaceAll("~~~ClassName~~~",
|
||||
class_.name);
|
||||
text = text.replaceAll("~~~ClassTLKDescription~~~",
|
||||
class_.text);
|
||||
// Add in the icon
|
||||
text = text.replaceAll("~~~Icon~~~", class_.iconPath);
|
||||
|
||||
// Add in the BAB and saving throws table
|
||||
text = text.replaceAll("~~~ClassBABAndSavThrTable~~~", buildBabAndSaveTable(class_));
|
||||
|
||||
// Add in the skills table
|
||||
text = text.replaceAll("~~~ClassSkillTable~~~", buildSkillTable(class_));
|
||||
|
||||
// Add in the feat table
|
||||
text = text.replaceAll("~~~ClassFeatTable~~~", buildClassFeatTables(class_));
|
||||
|
||||
// Add in the spells / powers table
|
||||
text = text.replaceAll("~~~ClassSpellAndPowerTables~~~", buildClassSpellAndPowerTables(class_));
|
||||
|
||||
|
||||
// Print the page
|
||||
try {
|
||||
printPage(class_.filePath, text);
|
||||
} catch (PageGenerationException e) {
|
||||
err_pr.println("Error: Exception when writing page for class " + class_.entryNum + ": " + class_.name + ":\n" + e);
|
||||
}
|
||||
}
|
||||
System.gc();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs the html table of levels and their bab + saving throw bonus values.
|
||||
*
|
||||
* @param class_ The class entry data structure of the class to generate the table for
|
||||
* @return string representation of the table
|
||||
*/
|
||||
private static String buildBabAndSaveTable(ClassEntry class_) {
|
||||
String toReturn = "";
|
||||
if (class_.babSav.size() != 0) {
|
||||
toReturn += babAndSavthrTableHeaderTemplate + "\n";
|
||||
// Start building the table
|
||||
for (int i = 0; i < class_.babSav.size(); i++) {
|
||||
toReturn += "<tr>\n";
|
||||
toReturn += classTablesEntryTemplate.replaceAll("~~~Entry~~~", (i + 1) + "");
|
||||
toReturn += classTablesEntryTemplate.replaceAll("~~~Entry~~~", class_.babSav.get(i)[0]);
|
||||
toReturn += classTablesEntryTemplate.replaceAll("~~~Entry~~~", class_.babSav.get(i)[1]);
|
||||
toReturn += classTablesEntryTemplate.replaceAll("~~~Entry~~~", class_.babSav.get(i)[2]);
|
||||
toReturn += classTablesEntryTemplate.replaceAll("~~~Entry~~~", class_.babSav.get(i)[3]);
|
||||
toReturn += "</tr>\n";
|
||||
}
|
||||
toReturn += "</table>\n";
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the html table of the class & cross-class skills of this class.
|
||||
* TreeMaps are used to arrange the printed skills in alphabetic order.
|
||||
*
|
||||
* @param class_ The class entry data structure of the class to generate the table for
|
||||
* @return string representation of the table
|
||||
*/
|
||||
private static String buildSkillTable(ClassEntry class_) {
|
||||
String toReturn = skillTableHeaderTemplate;
|
||||
GenericEntry tempSkill = null;
|
||||
// Clone the maps, since we'll be performing destructive operations on them
|
||||
TreeMap<String, GenericEntry> classSkills = new TreeMap<String, GenericEntry>(class_.skillList.e1),
|
||||
crossClassSkills = new TreeMap<String, GenericEntry>(class_.skillList.e2);
|
||||
|
||||
while (classSkills.size() > 0 || crossClassSkills.size() > 0) {
|
||||
toReturn += "<tr>\n";
|
||||
|
||||
if (classSkills.size() > 0) {
|
||||
tempSkill = classSkills.remove(classSkills.firstKey());
|
||||
toReturn += classTablesEntryTemplate.replaceAll("~~~Entry~~~", "<a href=\"" + tempSkill.filePath.replace(contentPath, "../").replaceAll("\\\\", "/") + "\" target=\"content\">" + tempSkill.name + "</a>");
|
||||
} else
|
||||
toReturn += classTablesEntryTemplate.replaceAll("~~~Entry~~~", " ");
|
||||
|
||||
if (crossClassSkills.size() > 0) {
|
||||
tempSkill = crossClassSkills.remove(crossClassSkills.firstKey());
|
||||
toReturn += classTablesEntryTemplate.replaceAll("~~~Entry~~~", "<a href=\"" + tempSkill.filePath.replace(contentPath, "../").replaceAll("\\\\", "/") + "\" target=\"content\">" + tempSkill.name + "</a>");
|
||||
} else
|
||||
toReturn += classTablesEntryTemplate.replaceAll("~~~Entry~~~", " ");
|
||||
|
||||
toReturn += "</tr>\n";
|
||||
}
|
||||
|
||||
toReturn += "</table>\n";
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs the html table of the bonus and selectable class feats of the given class.
|
||||
* TreeMaps are used to arrange the printed feats in alphabetic order.
|
||||
*
|
||||
* @param class_ The class entry data structure of the class to generate the table for
|
||||
* @return String that contains the table
|
||||
*/
|
||||
private static String buildClassFeatTables(ClassEntry class_) {
|
||||
List<TreeMap<String, FeatEntry>> grantedFeatList = class_.featList.e2.e1,
|
||||
selectableFeatList = class_.featList.e2.e2;
|
||||
List<Integer> bonusFeatCounts = class_.featList.e1;
|
||||
|
||||
// Start constructing the table
|
||||
StringBuffer tableText = new StringBuffer();
|
||||
StringBuffer linkList = null;
|
||||
String tableLine = null;
|
||||
for (int i = 0; i < grantedFeatList.size(); i++) {
|
||||
tableLine = classFeatTableEntryTemplate.replace("~~~Level~~~", String.valueOf(i + 1))
|
||||
.replace("~~~NumberOfBonusFeats~~~", bonusFeatCounts.get(i).toString());
|
||||
// Generate the granted feats list
|
||||
linkList = new StringBuffer();
|
||||
if (grantedFeatList.get(i) != null)
|
||||
for (FeatEntry feat : grantedFeatList.get(i).values()) {
|
||||
linkList.append(pageLinkTemplate.replace("~~~Path~~~", feat.filePath.replace(contentPath, "../").replaceAll("\\\\", "/"))
|
||||
.replace("~~~Name~~~", feat.name));
|
||||
}
|
||||
else
|
||||
linkList.append(" ");
|
||||
tableLine = tableLine.replace("~~~FeatsGrantedList~~~", linkList.toString());
|
||||
|
||||
// Generate the granted feats list
|
||||
linkList = new StringBuffer();
|
||||
if (selectableFeatList.get(i) != null)
|
||||
for (FeatEntry feat : selectableFeatList.get(i).values()) {
|
||||
linkList.append(pageLinkTemplate.replace("~~~Path~~~", feat.filePath.replace(contentPath, "../").replaceAll("\\\\", "/"))
|
||||
.replace("~~~Name~~~", feat.name));
|
||||
}
|
||||
else
|
||||
linkList.append(" ");
|
||||
tableLine = tableLine.replace("~~~SelectableFeatsList~~~", linkList.toString());
|
||||
|
||||
// Append the line to the table
|
||||
tableText.append(tableLine);
|
||||
}
|
||||
|
||||
return classFeatTableTemplate.replace("~~~TableContents~~~", tableText.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the html table of the new spellbook spells and psionic powers lists of
|
||||
* the given class. The entries are ordered by spell / power level
|
||||
*
|
||||
* @param class_ The class entry data structure of the class to generate the table for
|
||||
* @return String that contains the table
|
||||
*/
|
||||
private static String buildClassSpellAndPowerTables(ClassEntry class_) {
|
||||
StringBuffer toReturn = new StringBuffer();
|
||||
|
||||
for (Tuple<Tuple<String, String>, TreeMap<Integer, TreeMap<String, SpellEntry>>> magicData : class_.magics) {
|
||||
// Map of level numbers to maps of spell names to html links. Cloned due to destructive operations
|
||||
TreeMap<Integer, TreeMap<String, SpellEntry>> levelLists =
|
||||
new TreeMap<Integer, TreeMap<String, SpellEntry>>(magicData.e2);
|
||||
|
||||
StringBuffer tableLines = new StringBuffer(),
|
||||
spellLinks;
|
||||
String tableLine;
|
||||
while (levelLists.size() > 0) {
|
||||
tableLine = classMagicTableEntryTemplate.replace("~~~Level~~~", levelLists.firstKey().toString());
|
||||
spellLinks = new StringBuffer();
|
||||
for (SpellEntry spell : levelLists.remove(levelLists.firstKey()).values())
|
||||
spellLinks.append(pageLinkTemplate.replace("~~~Path~~~", spell.filePath.replace(contentPath, "../").replaceAll("\\\\", "/"))
|
||||
.replace("~~~Name~~~", spell.name));
|
||||
tableLines.append(tableLine.replace("~~~EntryList~~~", spellLinks.toString()));
|
||||
}
|
||||
|
||||
toReturn.append(classMagicTableTemplate.replace("~~~TableName~~~", magicData.e1.e1)
|
||||
.replace("~~~Type~~~", magicData.e1.e2)
|
||||
.replace("~~~TableContents~~~", tableLines.toString()));
|
||||
}
|
||||
|
||||
return toReturn.toString();
|
||||
}
|
||||
}
|
Binary file not shown.
@@ -0,0 +1,23 @@
|
||||
package prc.autodoc;
|
||||
|
||||
/**
|
||||
* An exception indicating failure while generating a page.
|
||||
*/
|
||||
public class PageGenerationException extends java.lang.RuntimeException{
|
||||
private static final long serialVersionUID = 0x2L;
|
||||
|
||||
/**
|
||||
* Creates a new exception.
|
||||
*
|
||||
* @param message The message this exception is to carry
|
||||
*/
|
||||
public PageGenerationException(String message) { super(message); }
|
||||
|
||||
/**
|
||||
* Creates a new exception.
|
||||
*
|
||||
* @param message The message this exception is to carry
|
||||
* @param cause Another exception that caused this one to be thrown
|
||||
*/
|
||||
public PageGenerationException(String message, Throwable cause){ super(message, cause); }
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/RaceEntry.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/RaceEntry.class
Normal file
Binary file not shown.
29
nwn/nwnprc/DocGen/trunk/prc/autodoc/RaceEntry.java
Normal file
29
nwn/nwnprc/DocGen/trunk/prc/autodoc/RaceEntry.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package prc.autodoc;
|
||||
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* Data structure for a race entry.
|
||||
*/
|
||||
public class RaceEntry extends GenericEntry {
|
||||
|
||||
/**
|
||||
* A list of masterfeat's children
|
||||
*/
|
||||
public final TreeMap<String, FeatEntry> raceFeats;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*
|
||||
* @param name Name of the race
|
||||
* @param text Description of the race
|
||||
* @param filePath Path where the html page for this race will be written to
|
||||
* @param entryNum racialtypes.2da index
|
||||
* @param raceFeats Racial feat list
|
||||
*/
|
||||
public RaceEntry(String name, String text, String filePath,
|
||||
int entryNum, TreeMap<String, FeatEntry> raceFeats) {
|
||||
super(name, text, null, filePath, entryNum);
|
||||
this.raceFeats = raceFeats;
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/SpellEntry.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/SpellEntry.class
Normal file
Binary file not shown.
38
nwn/nwnprc/DocGen/trunk/prc/autodoc/SpellEntry.java
Normal file
38
nwn/nwnprc/DocGen/trunk/prc/autodoc/SpellEntry.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package prc.autodoc;
|
||||
|
||||
import prc.autodoc.Main.SpellType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Data structure for a spell entry.
|
||||
*/
|
||||
public class SpellEntry extends GenericEntry {
|
||||
/**
|
||||
* Type of this spell entry
|
||||
*/
|
||||
public final SpellType type;
|
||||
|
||||
/**
|
||||
* The spell's subradials, if any. List of spell name, icon path tuples.
|
||||
*/
|
||||
public final List<Tuple<String, String>> subradials;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*
|
||||
* @param name Name of the spell
|
||||
* @param text Description of the spell
|
||||
* @param iconPath Path of the spell's icon
|
||||
* @param filePath Path of the html file describing the spell.
|
||||
* @param entryNum spells.2da index
|
||||
* @param type Type of the spell: Normal / Epic / Psionic / whatever
|
||||
* @param subradials
|
||||
*/
|
||||
public SpellEntry(String name, String text, String iconPath, String filePath,
|
||||
int entryNum, SpellType type, List<Tuple<String, String>> subradials) {
|
||||
super(name, text, iconPath, filePath, entryNum);
|
||||
this.type = type;
|
||||
this.subradials = subradials;
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Spinner.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Spinner.class
Normal file
Binary file not shown.
34
nwn/nwnprc/DocGen/trunk/prc/autodoc/Spinner.java
Normal file
34
nwn/nwnprc/DocGen/trunk/prc/autodoc/Spinner.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package prc.autodoc;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* An absolutely critical part of the Document Creator, not. Prints a spinning line
|
||||
* for the user to look at while the program is working.
|
||||
*/
|
||||
public final class Spinner {
|
||||
private final char[] states = new char[]{'|', '/', '-', '\\'};
|
||||
private int curState = 0;
|
||||
private boolean active = true;
|
||||
private Date lastSpinTime = new Date();
|
||||
|
||||
|
||||
/**
|
||||
* Spins the spinner.
|
||||
*/
|
||||
public void spin() {
|
||||
long minTimeBetweenSpinsInMS = 300;
|
||||
if (active && new Date().getTime() - lastSpinTime.getTime() > minTimeBetweenSpinsInMS) {
|
||||
System.out.print(states[curState = ++curState % states.length] + "\u0008");
|
||||
lastSpinTime = new Date();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Turns the spinner off.
|
||||
*/
|
||||
public void disable() {
|
||||
active = false;
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/TLKReadException.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/TLKReadException.class
Normal file
Binary file not shown.
23
nwn/nwnprc/DocGen/trunk/prc/autodoc/TLKReadException.java
Normal file
23
nwn/nwnprc/DocGen/trunk/prc/autodoc/TLKReadException.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package prc.autodoc;
|
||||
|
||||
/**
|
||||
* An exception indicating TLK read failed.
|
||||
*/
|
||||
public class TLKReadException extends java.lang.RuntimeException{
|
||||
private static final long serialVersionUID = 0x0L;
|
||||
|
||||
/**
|
||||
* Creates a new exception.
|
||||
*
|
||||
* @param message The message this exception is to carry
|
||||
*/
|
||||
public TLKReadException(String message) { super(message); }
|
||||
|
||||
/**
|
||||
* Creates a new exception.
|
||||
*
|
||||
* @param message The message this exception is to carry
|
||||
* @param cause Another exception that caused this one to be thrown
|
||||
*/
|
||||
public TLKReadException(String message, Throwable cause){ super(message, cause); }
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Tuple.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Tuple.class
Normal file
Binary file not shown.
30
nwn/nwnprc/DocGen/trunk/prc/autodoc/Tuple.java
Normal file
30
nwn/nwnprc/DocGen/trunk/prc/autodoc/Tuple.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package prc.autodoc;
|
||||
|
||||
/**
|
||||
* A simple tuple class
|
||||
*
|
||||
* @param <T1> The type of the first element of the tuple
|
||||
* @param <T2> The type of the second element of the tuple
|
||||
* @author Ornedan
|
||||
*/
|
||||
public class Tuple<T1, T2> {
|
||||
/**
|
||||
* The first element
|
||||
*/
|
||||
public final T1 e1;
|
||||
/**
|
||||
* The second element
|
||||
*/
|
||||
public final T2 e2;
|
||||
|
||||
/**
|
||||
* Generates a new tuple out of the given two objects.
|
||||
*
|
||||
* @param e1 The object to become the first element of the new tuple
|
||||
* @param e2 The object to become the second element of the new tuple
|
||||
*/
|
||||
public Tuple(T1 e1, T2 e2) {
|
||||
this.e1 = e1;
|
||||
this.e2 = e2;
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/TwoDAReadException.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/TwoDAReadException.class
Normal file
Binary file not shown.
23
nwn/nwnprc/DocGen/trunk/prc/autodoc/TwoDAReadException.java
Normal file
23
nwn/nwnprc/DocGen/trunk/prc/autodoc/TwoDAReadException.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package prc.autodoc;
|
||||
|
||||
/**
|
||||
* An exception indicating 2da read failed.
|
||||
*/
|
||||
public class TwoDAReadException extends java.lang.RuntimeException{
|
||||
private static final long serialVersionUID = 0x1L;
|
||||
|
||||
/**
|
||||
* Creates a new exception.
|
||||
*
|
||||
* @param message The message this exception is to carry
|
||||
*/
|
||||
public TwoDAReadException(String message) { super(message); }
|
||||
|
||||
/**
|
||||
* Creates a new exception.
|
||||
*
|
||||
* @param message The message this exception is to carry
|
||||
* @param cause Another exception that caused this one to be thrown
|
||||
*/
|
||||
public TwoDAReadException(String message, Throwable cause){ super(message, cause); }
|
||||
}
|
Reference in New Issue
Block a user