Added LF to CR-LF conversion, and warnings
This commit is contained in:
parent
5f289a0bef
commit
9b34c5119f
5 changed files with 126 additions and 32 deletions
|
@ -1,13 +1,17 @@
|
|||
Changelog
|
||||
|
||||
???:
|
||||
- Added LF to CR-LF conversion for *.xml.append, *.xml, and *.txt
|
||||
- Added a Validate warning for text files with LF line endings
|
||||
|
||||
1.0:
|
||||
- Changed mod list to a table with checkboxes
|
||||
- Instead of extracting to temp, mod data is transferred directly into dats
|
||||
- Added a GUI progress bar during patching
|
||||
- Added a Validate warning for paths with non-ASCII chars
|
||||
- Added support for windows-1252 ANSI and UTF-16 text in mods
|
||||
|
||||
Changes shared with Grognaks Mod Manager 1.8:
|
||||
- Added support for windows-1252 ANSI and UTF-16 text in mods
|
||||
- Added periodic updates to the catalog of mod metadata
|
||||
- Added ini setting: update_catalog
|
||||
- Added a log warning during patching if a mod gets clobbered
|
||||
|
|
|
@ -30,17 +30,22 @@ The Append Extension
|
|||
to your pleasure by writing an event of the same name. Whenever multiple
|
||||
tags share the same name, only the last one counts.
|
||||
|
||||
When you're not overriding something, try to use unique names, so that
|
||||
it won't clobber another mod and vice versa.
|
||||
|
||||
|
||||
General
|
||||
|
||||
When developing a mod, save your text files as ANSI/ASCII, or UTF-8.
|
||||
UTF-16 is tolerated. If all else fails, Slipstream will try decoding
|
||||
text as Windows-1252 ANSI.
|
||||
Slipstream will tolerate UTF-16 and Windows-1252 ANSI.
|
||||
|
||||
Unless you're overriding something, try to use unique names in your xml
|
||||
so that it won't clobber another mod and vice versa. File and directory
|
||||
names must be plain ASCII (no accents). That restriction isn't confirmed
|
||||
for the game, but the mod manager enforces it just to be safe.
|
||||
Dos style (CR-LF) line endings are preferred. The game only partially
|
||||
accepts the unix style (LF): fine for xml, crashing for layout.txt.
|
||||
Slipstream will convert both to CR-LF as it patches.
|
||||
|
||||
File and directory names must be plain ASCII (no accents). That
|
||||
restriction isn't confirmed for the game, but the mod manager enforces
|
||||
it just to be safe.
|
||||
|
||||
Images should be 32bit PNGs (24bit color + 8bit alpha transparency).
|
||||
Things that *should* be opaque rectangles like backgrounds may vary,
|
||||
|
|
|
@ -26,7 +26,7 @@ public class FTLModManager {
|
|||
private static final Logger log = LogManager.getLogger(FTLModManager.class);
|
||||
|
||||
private static final String APP_NAME = "Slipstream Mod Manager";
|
||||
private static final ComparableVersion APP_VERSION = new ComparableVersion( "1.0" );
|
||||
private static final ComparableVersion APP_VERSION = new ComparableVersion( "???" );
|
||||
private static final String APP_URL = "http://www.ftlgame.com/forum/viewtopic.php?f=12&t=17102";
|
||||
private static final String APP_AUTHOR = "Vhati";
|
||||
|
||||
|
@ -34,8 +34,8 @@ public class FTLModManager {
|
|||
public static void main( String[] args ) {
|
||||
|
||||
log.debug( String.format( "%s v%s", APP_NAME, APP_VERSION ) );
|
||||
log.debug( System.getProperty("os.name") +" "+ System.getProperty("os.version") +" "+ System.getProperty("os.arch") );
|
||||
log.debug( System.getProperty("java.vm.name") +", "+ System.getProperty("java.version") );
|
||||
log.debug( String.format( "%s %s", System.getProperty("os.name"), System.getProperty("os.version") ) );
|
||||
log.debug( String.format( "%s, %s, %s", System.getProperty("java.vm.name"), System.getProperty("java.version"), System.getProperty("os.arch") ) );
|
||||
|
||||
|
||||
File configFile = new File( "modman.cfg" );
|
||||
|
@ -154,7 +154,9 @@ public class FTLModManager {
|
|||
configComments += " update_catalog - If true, periodically download descriptions for the latest mods. If invalid, you'll be prompted.\n";
|
||||
configComments += " use_default_ui - If true, no attempt will be made to resemble a native GUI. Default: false.\n";
|
||||
|
||||
config.store( new OutputStreamWriter( out, "UTF-8" ), configComments );
|
||||
OutputStreamWriter writer = new OutputStreamWriter( out, "UTF-8" );
|
||||
config.store( writer, configComments );
|
||||
writer.flush();
|
||||
}
|
||||
catch ( IOException e ) {
|
||||
log.error( "Error saving config to "+ configFile.getPath(), e );
|
||||
|
|
|
@ -233,6 +233,21 @@ public class ModPatchThread extends Thread {
|
|||
moddedItems.add( innerPath );
|
||||
}
|
||||
}
|
||||
else if ( fileName.endsWith( ".xml" ) || fileName.endsWith( ".txt" ) ) {
|
||||
String innerPath = checkCase( item.getName(), knownPaths, knownPathsLower );
|
||||
|
||||
// Normalize line endings for other text files to CR-LF.
|
||||
InputStream fixedStream = ModUtilities.setLineEndings( zis, "\r\n", modFile.getName()+":"+parentPath+fileName );
|
||||
|
||||
if ( !moddedItems.contains(innerPath) )
|
||||
moddedItems.add( innerPath );
|
||||
else
|
||||
log.warn( String.format( "Clobbering earlier mods: %s", innerPath ) );
|
||||
|
||||
if ( ftlP.contains( innerPath ) )
|
||||
ftlP.remove( innerPath );
|
||||
ftlP.add( innerPath, fixedStream );
|
||||
}
|
||||
else {
|
||||
String innerPath = checkCase( item.getName(), knownPaths, knownPathsLower );
|
||||
|
||||
|
|
|
@ -112,8 +112,17 @@ public class ModUtilities {
|
|||
}
|
||||
}
|
||||
|
||||
// Determine the original line endings.
|
||||
int eol = DecodeResult.EOL_NONE;
|
||||
Matcher m = Pattern.compile( "(\r(?!\n))|((?<!\r)\n)|(\r\n)" ).matcher( result );
|
||||
if ( m.find() ) {
|
||||
if ( m.group(3) != null ) eol = DecodeResult.EOL_CRLF;
|
||||
else if ( m.group(2) != null ) eol = DecodeResult.EOL_LF;
|
||||
else if ( m.group(1) != null ) eol = DecodeResult.EOL_CR;
|
||||
}
|
||||
|
||||
result = result.replaceAll( "\r(?!\n)|\r\n", "\n" );
|
||||
return new DecodeResult( result, encoding, bom );
|
||||
return new DecodeResult( result, encoding, eol, bom );
|
||||
}
|
||||
|
||||
|
||||
|
@ -126,6 +135,8 @@ public class ModUtilities {
|
|||
* The returned stream is a ByteArrayInputStream
|
||||
* which doesn't need closing.
|
||||
*
|
||||
* The result will be UTF-8 with CR-LF line endings.
|
||||
*
|
||||
* The description arguments identify the streams for log messages.
|
||||
*/
|
||||
public static InputStream appendXMLFile( InputStream srcStream, InputStream dstStream, String srcDescription, String dstDescription ) throws IOException {
|
||||
|
@ -137,20 +148,50 @@ public class ModUtilities {
|
|||
String dstText = decodeText( dstStream, dstDescription ).text;
|
||||
dstText = xmlDeclPtn.matcher(dstText).replaceFirst( "" );
|
||||
|
||||
StringBuilder buf = new StringBuilder( srcText.length() +100+ dstText.length() );
|
||||
buf.append( "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" );
|
||||
buf.append( dstText );
|
||||
buf.append( "\n\n<!-- Appended by GMM -->\n\n" );
|
||||
buf.append( srcText );
|
||||
buf.append( "\n" );
|
||||
|
||||
String mergedString = Pattern.compile("\n").matcher( buf ).replaceAll("\r\n");
|
||||
|
||||
ByteArrayOutputStream tmpData = new ByteArrayOutputStream();
|
||||
BufferedWriter bw = new BufferedWriter( new OutputStreamWriter( tmpData, "UTF-8" ) );
|
||||
|
||||
bw.write( "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" );
|
||||
bw.write( dstText );
|
||||
bw.write( "\n\n<!-- Appended by GMM -->\n\n");
|
||||
bw.write( srcText );
|
||||
bw.write( "\n" );
|
||||
bw.write( mergedString );
|
||||
bw.flush();
|
||||
|
||||
InputStream result = new ByteArrayInputStream( tmpData.toByteArray() );
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calls decodeText() on a stream, replaces line endings, and re-encodes.
|
||||
*
|
||||
* The returned stream is a ByteArrayInputStream
|
||||
* which doesn't need closing.
|
||||
*
|
||||
* The result will be UTF-8 with the desired line endings.
|
||||
*
|
||||
* The description argument identifies the stream for log messages.
|
||||
*/
|
||||
public static InputStream setLineEndings( InputStream srcStream, String eol, String srcDescription ) throws IOException {
|
||||
// decodeText() returns a LF string.
|
||||
String srcText = decodeText( srcStream, srcDescription ).text;
|
||||
String fixedText = Pattern.compile("\n").matcher( srcText ).replaceAll( Matcher.quoteReplacement(eol) );
|
||||
|
||||
ByteArrayOutputStream tmpData = new ByteArrayOutputStream();
|
||||
BufferedWriter bw = new BufferedWriter( new OutputStreamWriter( tmpData, "UTF-8" ) );
|
||||
bw.write( fixedText );
|
||||
bw.flush();
|
||||
|
||||
InputStream result = new ByteArrayInputStream( tmpData.toByteArray() );
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks a mod file for common problems.
|
||||
*
|
||||
|
@ -215,7 +256,7 @@ public class ModUtilities {
|
|||
) );
|
||||
modValid = false;
|
||||
}
|
||||
else if ( innerPath.endsWith( ".png" ) ) {
|
||||
else if ( innerPath.endsWith( "[.]png" ) ) {
|
||||
try {
|
||||
PngReader pngr = new PngReader( zis );
|
||||
|
||||
|
@ -249,9 +290,7 @@ public class ModUtilities {
|
|||
modValid = false;
|
||||
}
|
||||
}
|
||||
else if ( innerPath.matches( "^.*(?:.xml.append|.append.xml|.xml)$" ) ) {
|
||||
if ( innerPath.matches( "^.*(?:.xml.append|.append.xml)$" ) )
|
||||
seenAppend = true;
|
||||
else if ( innerPath.matches( "^.*(?:[.]xml[.]append|[.]append[.]xml|[.]xml|[.]txt)$" ) ) {
|
||||
|
||||
DecodeResult decodeResult = ModUtilities.decodeText( zis, modFile.getName()+":"+innerPath );
|
||||
|
||||
|
@ -263,6 +302,15 @@ public class ModUtilities {
|
|||
modValid = false;
|
||||
}
|
||||
|
||||
if ( decodeResult.eol != DecodeResult.EOL_CRLF &&
|
||||
decodeResult.eol != DecodeResult.EOL_NONE ) {
|
||||
pendingMsgs.add( new ReportMessage(
|
||||
ReportMessage.ERROR,
|
||||
String.format( "%s line endings (CR-LF is safest)", decodeResult.getEOLName() )
|
||||
) );
|
||||
modValid = false;
|
||||
}
|
||||
|
||||
List<Pattern> oddCharPtns = new ArrayList<Pattern>();
|
||||
Map<Pattern,String> oddCharSuggestions = new HashMap<Pattern,String>();
|
||||
Map<Pattern,List<Character>> oddCharLists = new HashMap<Pattern,List<Character>>();
|
||||
|
@ -310,6 +358,10 @@ public class ModUtilities {
|
|||
|
||||
// TODO: Nag if there are chars FTL can't show.
|
||||
|
||||
if ( innerPath.matches( "^.*(?:[.]xml[.]append|[.]append[.]xml|[.]xml)$" ) ) {
|
||||
if ( innerPath.matches( "^.*(?:[.]xml[.]append|[.]append[.]xml)$" ) )
|
||||
seenAppend = true;
|
||||
|
||||
Report xmlReport = validateModXML( decodeResult.text, formatter );
|
||||
|
||||
if ( xmlReport.text.length() > 0 ) {
|
||||
|
@ -322,6 +374,7 @@ public class ModUtilities {
|
|||
if ( xmlReport.outcome == false )
|
||||
modValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !pendingMsgs.isEmpty() ) {
|
||||
messages.add( new ReportMessage(
|
||||
|
@ -644,17 +697,32 @@ public class ModUtilities {
|
|||
*
|
||||
* text - The decoded string.
|
||||
* encoding - The encoding used.
|
||||
* eol - A constant describing the original line endings.
|
||||
* bom - The BOM bytes found, or null.
|
||||
*/
|
||||
public static class DecodeResult {
|
||||
public static final int EOL_NONE = 0;
|
||||
public static final int EOL_CRLF = 1;
|
||||
public static final int EOL_LF = 2;
|
||||
public static final int EOL_CR = 3;
|
||||
|
||||
public final String text;
|
||||
public final String encoding;
|
||||
public final int eol;
|
||||
public final byte[] bom;
|
||||
|
||||
public DecodeResult( String text, String encoding, byte[] bom ) {
|
||||
public DecodeResult( String text, String encoding, int eol, byte[] bom ) {
|
||||
this.text = text;
|
||||
this.encoding = encoding;
|
||||
this.eol = eol;
|
||||
this.bom = bom;
|
||||
}
|
||||
|
||||
public String getEOLName() {
|
||||
if ( eol == EOL_CRLF ) return "CR-LF";
|
||||
if ( eol == EOL_LF ) return "LF";
|
||||
if ( eol == EOL_CR ) return "CR";
|
||||
return "None";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue