Skip to content

Commit

Permalink
Refactor custom names system completely.
Browse files Browse the repository at this point in the history
This combines everything into one binary file (customnames.rncn for
now). The GUI will now ask if you want to convert your old text files
into a new file, if they exist.

Still TODO:
* Create a GUI editor for custom names, since they are no longer in
plaintext files
* Refactor ROM-side detection of doubles classes/trainers to no longer
use the dumb string tests that only (barely) work for English language.
Even constant value arrays of which classes are doubles classes will be
better.

This also fixes a minor bug with the new moveset randomization code.
  • Loading branch information
Dabomstew committed Apr 26, 2016
1 parent b808177 commit 02f0960
Show file tree
Hide file tree
Showing 19 changed files with 397 additions and 508 deletions.
7 changes: 4 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@ bin
nbproject
build.xml
manifest.mf
nicknames.txt
trainerclasses.txt
trainernames.txt
/nicknames.txt
/trainerclasses.txt
/trainernames.txt
/build/
*.dsm
*.dsv
build_eclipse.xml
/customnames.rncn
189 changes: 189 additions & 0 deletions src/com/dabomstew/pkrandom/CustomNamesSet.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
package com.dabomstew.pkrandom;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;

public class CustomNamesSet {

private List<String> trainerNames;
private List<String> trainerClasses;
private List<String> doublesTrainerNames;
private List<String> doublesTrainerClasses;
private List<String> pokemonNicknames;

private static final int CUSTOM_NAMES_VERSION = 1;

// Standard constructor: read binary data from an input stream.
public CustomNamesSet(InputStream data) throws IOException {

if (data.read() != CUSTOM_NAMES_VERSION) {
throw new IOException("Invalid custom names file provided.");
}

trainerNames = readNamesBlock(data);
trainerClasses = readNamesBlock(data);
doublesTrainerNames = readNamesBlock(data);
doublesTrainerClasses = readNamesBlock(data);
pokemonNicknames = readNamesBlock(data);
}

// Private constructor: blank all lists.
// Used for importing old names.
private CustomNamesSet() {
trainerNames = new ArrayList<String>();
trainerClasses = new ArrayList<String>();
doublesTrainerNames = new ArrayList<String>();
doublesTrainerClasses = new ArrayList<String>();
pokemonNicknames = new ArrayList<String>();
}

private List<String> readNamesBlock(InputStream in) throws IOException {
// Read the size of the block to come.
byte[] szData = FileFunctions.readFullyIntoBuffer(in, 4);
int size = FileFunctions.readFullInt(szData, 0);
if (in.available() < size) {
throw new IOException("Invalid size specified.");
}

// Read the block and translate it into a list of names.
byte[] namesData = FileFunctions.readFullyIntoBuffer(in, size);
List<String> names = new ArrayList<String>();
Scanner sc = new Scanner(new ByteArrayInputStream(namesData), "UTF-8");
while (sc.hasNextLine()) {
String name = sc.nextLine().trim();
if (!name.isEmpty()) {
names.add(name);
}
}
sc.close();

return names;
}

public byte[] getBytes() throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();

baos.write(CUSTOM_NAMES_VERSION);

writeNamesBlock(baos, trainerNames);
writeNamesBlock(baos, trainerClasses);
writeNamesBlock(baos, doublesTrainerNames);
writeNamesBlock(baos, doublesTrainerClasses);
writeNamesBlock(baos, pokemonNicknames);

return baos.toByteArray();
}

private void writeNamesBlock(OutputStream out, List<String> names) throws IOException {
String newln = System.getProperty("line.separator");
StringBuffer outNames = new StringBuffer();
boolean first = true;
for (String name : names) {
if (!first) {
outNames.append(newln);
}
first = false;
outNames.append(name);
}
byte[] namesData = outNames.toString().getBytes("UTF-8");
byte[] szData = new byte[4];
FileFunctions.writeFullInt(szData, 0, namesData.length);
out.write(szData);
out.write(namesData);
}

public List<String> getTrainerNames() {
return Collections.unmodifiableList(trainerNames);
}

public List<String> getTrainerClasses() {
return Collections.unmodifiableList(trainerClasses);
}

public List<String> getDoublesTrainerNames() {
return Collections.unmodifiableList(doublesTrainerNames);
}

public List<String> getDoublesTrainerClasses() {
return Collections.unmodifiableList(doublesTrainerClasses);
}

public List<String> getPokemonNicknames() {
return Collections.unmodifiableList(pokemonNicknames);
}

public static CustomNamesSet importOldNames() throws FileNotFoundException {
CustomNamesSet cns = new CustomNamesSet();

// Trainer Names
if (FileFunctions.configExists(SysConstants.tnamesFile)) {
Scanner sc = new Scanner(FileFunctions.openConfig(SysConstants.tnamesFile), "UTF-8");
while (sc.hasNextLine()) {
String trainername = sc.nextLine().trim();
if (trainername.isEmpty()) {
continue;
}
if (trainername.startsWith("\uFEFF")) {
trainername = trainername.substring(1);
}
if (trainername.contains("&")) {
cns.doublesTrainerNames.add(trainername);
} else {
cns.trainerNames.add(trainername);
}
}
sc.close();
}

// Trainer Classes
if (FileFunctions.configExists(SysConstants.tclassesFile)) {
Scanner sc = new Scanner(FileFunctions.openConfig(SysConstants.tclassesFile), "UTF-8");
while (sc.hasNextLine()) {
String trainerClassName = sc.nextLine().trim();
if (trainerClassName.isEmpty()) {
continue;
}
if (trainerClassName.startsWith("\uFEFF")) {
trainerClassName = trainerClassName.substring(1);
}
String checkName = trainerClassName.toLowerCase();
int idx = (checkName.endsWith("couple") || checkName.contains(" and ") || checkName.endsWith("kin")
|| checkName.endsWith("team") || checkName.contains("&") || (checkName.endsWith("s") && !checkName
.endsWith("ss"))) ? 1 : 0;
if (idx == 1) {
cns.doublesTrainerClasses.add(trainerClassName);
} else {
cns.trainerClasses.add(trainerClassName);
}
}
sc.close();
}

// Nicknames
if (FileFunctions.configExists(SysConstants.nnamesFile)) {
Scanner sc = new Scanner(FileFunctions.openConfig(SysConstants.nnamesFile), "UTF-8");
while (sc.hasNextLine()) {
String nickname = sc.nextLine().trim();
if (nickname.isEmpty()) {
continue;
}
if (nickname.startsWith("\uFEFF")) {
nickname = nickname.substring(1);
}
cns.pokemonNicknames.add(nickname);
}
sc.close();
}

return cns;
}

}
18 changes: 16 additions & 2 deletions src/com/dabomstew/pkrandom/FileFunctions.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
Expand Down Expand Up @@ -66,8 +67,8 @@ public static File fixFilename(File original, String defaultExtension, List<Stri
return new File(original.getAbsolutePath().replace(original.getName(), "") + filename);
}

private static List<String> overrideFiles = Arrays.asList(new String[] { "trainerclasses.txt", "trainernames.txt",
"nicknames.txt" });
private static List<String> overrideFiles = Arrays.asList(new String[] { SysConstants.customNamesFile,
SysConstants.tclassesFile, SysConstants.tnamesFile, SysConstants.nnamesFile });

public static boolean configExists(String filename) {
if (overrideFiles.contains(filename)) {
Expand Down Expand Up @@ -97,6 +98,13 @@ public static InputStream openConfig(String filename) throws FileNotFoundExcepti
return FileFunctions.class.getResourceAsStream("/com/dabomstew/pkrandom/config/" + filename);
}

public static CustomNamesSet getCustomNames() throws IOException {
InputStream is = openConfig(SysConstants.customNamesFile);
CustomNamesSet cns = new CustomNamesSet(is);
is.close();
return cns;
}

public static int readFullInt(byte[] data, int offset) {
ByteBuffer buf = ByteBuffer.allocate(4).put(data, offset, 4);
buf.rewind();
Expand Down Expand Up @@ -140,6 +148,12 @@ public static void readFully(InputStream in, byte[] buf, int offset, int length)
}
}

public static void writeBytesToFile(String filename, byte[] data) throws IOException {
FileOutputStream fos = new FileOutputStream(filename);
fos.write(data);
fos.close();
}

public static byte[] getConfigAsBytes(String filename) throws IOException {
InputStream in = openConfig(filename);
byte[] buf = readFullyIntoBuffer(in, in.available());
Expand Down
14 changes: 6 additions & 8 deletions src/com/dabomstew/pkrandom/Randomizer.java
Original file line number Diff line number Diff line change
Expand Up @@ -311,11 +311,11 @@ public int randomize(final String filename, final PrintStream log, long seed) {

if (romHandler.canChangeTrainerText()) {
if (settings.isRandomizeTrainerClassNames()) {
romHandler.randomizeTrainerClassNames(settings.getTrainerClasses());
romHandler.randomizeTrainerClassNames(settings.getCustomNames());
}

if (settings.isRandomizeTrainerNames()) {
romHandler.randomizeTrainerNames(settings.getTrainerNames());
romHandler.randomizeTrainerNames(settings.getCustomNames());
}
}

Expand Down Expand Up @@ -480,15 +480,13 @@ public int randomize(final String filename, final PrintStream log, long seed) {
// In-game trades
List<IngameTrade> oldTrades = romHandler.getIngameTrades();
if (settings.getInGameTradesMod() == Settings.InGameTradesMod.RANDOMIZE_GIVEN) {
romHandler.randomizeIngameTrades(false, settings.getNicknames(),
settings.isRandomizeInGameTradesNicknames(), settings.getTrainerNames(),
romHandler.randomizeIngameTrades(false, settings.isRandomizeInGameTradesNicknames(),
settings.isRandomizeInGameTradesOTs(), settings.isRandomizeInGameTradesIVs(),
settings.isRandomizeInGameTradesItems());
settings.isRandomizeInGameTradesItems(), settings.getCustomNames());
} else if (settings.getInGameTradesMod() == Settings.InGameTradesMod.RANDOMIZE_GIVEN_AND_REQUESTED) {
romHandler.randomizeIngameTrades(true, settings.getNicknames(),
settings.isRandomizeInGameTradesNicknames(), settings.getTrainerNames(),
romHandler.randomizeIngameTrades(true, settings.isRandomizeInGameTradesNicknames(),
settings.isRandomizeInGameTradesOTs(), settings.isRandomizeInGameTradesIVs(),
settings.isRandomizeInGameTradesItems());
settings.isRandomizeInGameTradesItems(), settings.getCustomNames());
}

if (!(settings.getInGameTradesMod() == Settings.InGameTradesMod.UNCHANGED)) {
Expand Down
44 changes: 11 additions & 33 deletions src/com/dabomstew/pkrandom/Settings.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,11 @@

public class Settings {

public static final int VERSION = 171;
public static final int VERSION = 172;

public static final int LENGTH_OF_SETTINGS_DATA = 35;

private byte[] trainerClasses;
private byte[] trainerNames;
private byte[] nicknames;
private CustomNamesSet customNames;

private String romName;
private boolean updatedFromOldVersion = false;
Expand Down Expand Up @@ -397,9 +395,7 @@ public String toString() {

try {
writeFullInt(out, (int) checksum.getValue());
writeFullInt(out, FileFunctions.getFileChecksum("trainerclasses.txt"));
writeFullInt(out, FileFunctions.getFileChecksum("trainernames.txt"));
writeFullInt(out, FileFunctions.getFileChecksum("nicknames.txt"));
writeFullInt(out, FileFunctions.getFileChecksum(SysConstants.customNamesFile));
} catch (IOException e) {
}

Expand Down Expand Up @@ -703,31 +699,13 @@ public TweakForROMFeedback tweakForRom(RomHandler rh) {
}

// getters and setters

public byte[] getTrainerClasses() {
return trainerClasses;
}

public Settings setTrainerClasses(byte[] trainerClasses) {
this.trainerClasses = trainerClasses;
return this;
}

public byte[] getTrainerNames() {
return trainerNames;

public CustomNamesSet getCustomNames() {
return customNames;
}

public Settings setTrainerNames(byte[] trainerNames) {
this.trainerNames = trainerNames;
return this;
}

public byte[] getNicknames() {
return nicknames;
}

public Settings setNicknames(byte[] nicknames) {
this.nicknames = nicknames;

public Settings setCustomNames(CustomNamesSet customNames) {
this.customNames = customNames;
return this;
}

Expand Down Expand Up @@ -1576,12 +1554,12 @@ private static int getSetEnum(String type, boolean... bools) {

private static void checkChecksum(byte[] data) {
// Check the checksum
ByteBuffer buf = ByteBuffer.allocate(4).put(data, data.length - 16, 4);
ByteBuffer buf = ByteBuffer.allocate(4).put(data, data.length - 8, 4);
buf.rewind();
int crc = buf.getInt();

CRC32 checksum = new CRC32();
checksum.update(data, 0, data.length - 16);
checksum.update(data, 0, data.length - 8);

if ((int) checksum.getValue() != crc) {
throw new IllegalArgumentException("Malformed input string");
Expand Down
12 changes: 9 additions & 3 deletions src/com/dabomstew/pkrandom/SettingsUpdater.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public class SettingsUpdater {
*/
public String update(int oldVersion, String configString) {
byte[] data = DatatypeConverter.parseBase64Binary(configString);
this.dataBlock = new byte[100];
this.dataBlock = new byte[200];
this.actualDataLength = data.length;
System.arraycopy(data, 0, this.dataBlock, 0, this.actualDataLength);

Expand Down Expand Up @@ -228,14 +228,20 @@ public String update(int oldVersion, String configString) {
insertExtraByte(20, (byte) 0);
insertExtraByte(22, (byte) 0);
}

if(oldVersion < 172) {
// 171 to 172: removed separate names files in favor of one unified file
// so two of the trailing checksums are gone
actualDataLength -= 8;
}

// fix checksum
CRC32 checksum = new CRC32();
checksum.update(dataBlock, 0, actualDataLength - 16);
checksum.update(dataBlock, 0, actualDataLength - 8);

// convert crc32 to int bytes
byte[] crcBuf = ByteBuffer.allocate(4).putInt((int) checksum.getValue()).array();
System.arraycopy(crcBuf, 0, dataBlock, actualDataLength - 16, 4);
System.arraycopy(crcBuf, 0, dataBlock, actualDataLength - 8, 4);

// have to make a new byte array to convert to base64
byte[] finalConfigString = new byte[actualDataLength];
Expand Down
Loading

0 comments on commit 02f0960

Please sign in to comment.