diff --git a/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/MineTweakerMod.java b/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/MineTweakerMod.java
index 4b7fd64..95f7187 100644
--- a/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/MineTweakerMod.java
+++ b/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/MineTweakerMod.java
@@ -57,7 +57,7 @@ import net.minecraftforge.common.MinecraftForge;
*
* @author Stan Hebben
*/
-@Mod(modid = MineTweakerMod.MODID, version = "3.0.9")
+@Mod(modid = MineTweakerMod.MODID, version = "3.0.9B")
@NetworkMod(clientSideRequired = true, serverSideRequired = true, channels = {MCPacketHandler.CHANNEL_SERVERSCRIPT, MCPacketHandler.CHANNEL_OPENBROWSER}, packetHandler = MCPacketHandler.class)
public class MineTweakerMod {
public static final String MODID = "MineTweaker3";
diff --git a/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/MineTweakerMod.java b/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/MineTweakerMod.java
index 57b6da8..71280cf 100644
--- a/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/MineTweakerMod.java
+++ b/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/MineTweakerMod.java
@@ -53,7 +53,7 @@ import net.minecraftforge.common.MinecraftForge;
*
* @author Stan Hebben
*/
-@Mod(modid = MineTweakerMod.MODID, version = "3.0.9")
+@Mod(modid = MineTweakerMod.MODID, version = "3.0.9B")
public class MineTweakerMod {
public static final String MODID = "MineTweaker3";
public static final String MCVERSION = "1.7.10";
diff --git a/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/MineTweakerMod.java b/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/MineTweakerMod.java
index c00d733..8f8a2ba 100644
--- a/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/MineTweakerMod.java
+++ b/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/MineTweakerMod.java
@@ -51,7 +51,7 @@ import net.minecraftforge.common.MinecraftForge;
*
* @author Stan Hebben
*/
-@Mod(modid = MineTweakerMod.MODID, version = "3.0.9")
+@Mod(modid = MineTweakerMod.MODID, version = "3.0.9B")
public class MineTweakerMod {
public static final String MODID = "MineTweaker3";
public static final String MCVERSION = "1.7.2";
diff --git a/MineTweaker3-Web/downloads.html b/MineTweaker3-Web/downloads.html
index c7f6b7a..7ac6ff5 100644
--- a/MineTweaker3-Web/downloads.html
+++ b/MineTweaker3-Web/downloads.html
@@ -82,32 +82,45 @@
Latest version
Development versions
Basic version (without mod support)
This version is recommended for development, as it won't need you to provide the libraries for every mod in it.
Full version (with mod support)
This version includes all mod support. You may need the development versions of the supported mods as well.
What's changed? Changelog
Archived versions
+ Version 3.0.9
+
+
Version 3.0.8B
- MineTweaker 3.0.8B for Minecraft 1.6.4
diff --git a/MineTweaker3-Web/index.html b/MineTweaker3-Web/index.html
index 022bb99..67f5491 100644
--- a/MineTweaker3-Web/index.html
+++ b/MineTweaker3-Web/index.html
@@ -98,9 +98,9 @@
diff --git a/buildSrc/src/main/java/minetweaker/tasks/JMorph.java b/buildSrc/src/main/java/minetweaker/tasks/JMorph.java
new file mode 100644
index 0000000..46e3312
--- /dev/null
+++ b/buildSrc/src/main/java/minetweaker/tasks/JMorph.java
@@ -0,0 +1,170 @@
+package minetweaker.tasks;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Properties;
+import java.util.Stack;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.gradle.api.DefaultTask;
+import org.gradle.api.tasks.InputDirectory;
+import org.gradle.api.tasks.InputFile;
+import org.gradle.api.tasks.TaskAction;
+
+/**
+ * Java preprocessor. Enables conditional modification of Java source files.
+ *
+ * @author Stan Hebben
+ */
+public class JMorph extends DefaultTask {
+ @InputDirectory
+ public File inputDir;
+
+ @InputFile
+ public File propertiesFile;
+
+ @TaskAction
+ public void doTask() {
+ try {
+ Properties properties = new Properties();
+ BufferedReader reader = new BufferedReader(new FileReader(propertiesFile));
+ properties.load(reader);
+ reader.close();
+
+ processDirectory(inputDir, properties);
+ } catch (IOException ex) {
+ Logger.getLogger(JMorph.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+
+ private static void processDirectory(File dir, Properties properties) throws IOException {
+ for (File file : dir.listFiles()) {
+ if (file.isFile()) {
+ if (file.getName().endsWith(".java") || file.getName().endsWith(".java.d")) {
+ processJavaFile(file, properties);
+ }
+ } else if (file.isDirectory()) {
+ processDirectory(file, properties);
+ }
+ }
+ }
+
+ private static void processJavaFile(File file, Properties properties) throws IOException {
+ StringBuilder output = new StringBuilder();
+
+ File outputFile = file.getName().endsWith(".java.d")
+ ? new File(file.getParentFile(), file.getName().substring(0, file.getName().length() - 2))
+ : file;
+
+ try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
+ String line = reader.readLine();
+ if (line == null) return;
+
+ Stack conditions = new Stack<>();
+ conditions.push(Boolean.TRUE);
+ do {
+ String trimmed = line.trim();
+ if (trimmed.startsWith("//#fileifdef")) {
+ String id = getIdentifier(trimmed, 13);
+ if (properties.containsKey(id)) {
+ if (file.getName().endsWith(".java.d")) {
+ outputFile = new File(file.getParentFile(), file.getName().substring(0, file.getName().length() - 2));
+ } else {
+ outputFile = file;
+ }
+ } else {
+ if (file.getName().endsWith(".java")) {
+ outputFile = new File(file.getParentFile(), file.getName() + ".d");
+ } else {
+ outputFile = file;
+ }
+ }
+ } else if (trimmed.startsWith("//#fileifndef")) {
+ String id = getIdentifier(trimmed, 14);
+ if (!properties.containsKey(id)) {
+ outputFile = file.getName().endsWith(".java.d")
+ ? new File(file.getParentFile(), file.getName().substring(0, file.getName().length() - 2))
+ : file;
+ } else {
+ outputFile = file.getName().endsWith(".java")
+ ? new File(file.getParentFile(), file.getName() + ".d")
+ : file;
+ }
+ } else if (trimmed.startsWith("//#ifdef")) {
+ String id = getIdentifier(trimmed, 9);
+ conditions.push(properties.containsKey(id));
+ } else if (trimmed.startsWith("//#ifndef")) {
+ String id = getIdentifier(trimmed, 10);
+ conditions.push(!properties.containsKey(id));
+ } else if (trimmed.startsWith("//#else")) {
+ conditions.push(!conditions.pop());
+ } else if (trimmed.startsWith("//#elseif")) {
+ conditions.pop();
+ String id = getIdentifier(trimmed, 10);
+ conditions.push(properties.containsKey(id));
+ } else if (trimmed.startsWith("//#endif")) {
+ conditions.pop();
+ if (conditions.isEmpty()) {
+ System.err.println("Error: too many #endifs in " + file.getName());
+ return;
+ }
+ } else if (trimmed.startsWith("//+")) {
+ if (conditions.peek()) line = uncomment(line).toString();
+ } else if (trimmed.length() != 0) {
+ if (!conditions.peek()) line = comment(line).toString();
+ }
+
+ output.append(line).append('\n');
+
+ line = reader.readLine();
+ } while (line != null);
+ }
+
+ if (outputFile != file)
+ file.delete();
+
+ try (FileWriter writer = new FileWriter(outputFile)) {
+ writer.append(output);
+ }
+ }
+
+ private static CharSequence comment(String line) {
+ StringBuilder output = new StringBuilder();
+ for (int i = 0; i < line.length(); i++) {
+ if (line.charAt(i) == ' ' || line.charAt(i) == '\t') {
+ output.append(line.charAt(i));
+ continue;
+ }
+ output.append("//+").append(line.substring(i));
+ break;
+ }
+ return output;
+ }
+
+ private static CharSequence uncomment(String line) {
+ StringBuilder output = new StringBuilder();
+ for (int i = 0; i < line.length(); i++) {
+ if (line.charAt(i) == ' ' || line.charAt(i) == '\t') {
+ output.append(line.charAt(i));
+ } else if (line.charAt(i) == '/' && line.charAt(i + 1) == '/' && line.charAt(i + 2) == '+') {
+ output.append(line.substring(i + 3));
+ break;
+ } else {
+ return line;
+ }
+ }
+ return output;
+ }
+
+ private static String getIdentifier(String line, int offset) {
+ int from = offset;
+ int to = offset;
+ if (!Character.isJavaIdentifierStart(line.charAt(to))) return null;
+ to++;
+ while (to < line.length() && Character.isJavaIdentifierPart(line.charAt(to))) to++;
+ return line.substring(from, to);
+ }
+}