Split source preprocessor into separate gradle plugin
This commit is contained in:
@@ -82,7 +82,7 @@ Do **NOT** edit any of the code in `versions/$MCVERSION/build/` as it is automat
|
|||||||
|
|
||||||
You can pass the original source code through the preprocessor if you wish to develop/debug with another version of Minecraft:
|
You can pass the original source code through the preprocessor if you wish to develop/debug with another version of Minecraft:
|
||||||
```bash
|
```bash
|
||||||
./gradle -PmcVersion=10904 :setCoreVersion # switches all sources in src/main to 1.9.4
|
./gradle :1.9.4:setCoreVersion # switches all sources in src/main to 1.9.4
|
||||||
```
|
```
|
||||||
If you do so, you'll also have to run `./gradlew :core:copySrg :core:setupDecompWorkspace :jGui:core:setupDecompWorkspace`,
|
If you do so, you'll also have to run `./gradlew :core:copySrg :core:setupDecompWorkspace :jGui:core:setupDecompWorkspace`,
|
||||||
followed by a refresh of the project in your IDE.
|
followed by a refresh of the project in your IDE.
|
||||||
@@ -91,7 +91,7 @@ Make sure to switch back to the most recent branch before committing!
|
|||||||
Care should also be taken that switching to a different branch and back doesn't introduce any uncommitted changes (e.g. due to different indention, especially in case of nested conditions).
|
Care should also be taken that switching to a different branch and back doesn't introduce any uncommitted changes (e.g. due to different indention, especially in case of nested conditions).
|
||||||
|
|
||||||
The `replaymod_at.cfg` file uses the same preprocessor but with different keywords (see already existent examples in that file).
|
The `replaymod_at.cfg` file uses the same preprocessor but with different keywords (see already existent examples in that file).
|
||||||
If required, more file extensions and keywords can be added to the implementation in `versions/preprocessor.gradle`.
|
If required, more file extensions and keywords can be added to the upstream implementation or the respective tasks.
|
||||||
|
|
||||||
### Versioning
|
### Versioning
|
||||||
The ReplayMod uses the versioning scheme outlined [here](http://mcforge.readthedocs.io/en/latest/conventions/versioning/)
|
The ReplayMod uses the versioning scheme outlined [here](http://mcforge.readthedocs.io/en/latest/conventions/versioning/)
|
||||||
|
|||||||
11
build.gradle
11
build.gradle
@@ -59,17 +59,6 @@ def gitDescribe() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: 'versions/preprocessor.gradle'
|
|
||||||
|
|
||||||
task setCoreVersion() {
|
|
||||||
doLast {
|
|
||||||
def vars = [MC: project.mcVersion as int, DEV_ENV: 1]
|
|
||||||
project.convertTree(vars, 'src/main/java')
|
|
||||||
project.convertTree(vars, 'src/main/resources')
|
|
||||||
project.file('versions/core/mcVersion').write(vars.MC.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def command(Object...cmd) {
|
def command(Object...cmd) {
|
||||||
def stdout = new ByteArrayOutputStream()
|
def stdout = new ByteArrayOutputStream()
|
||||||
exec {
|
exec {
|
||||||
|
|||||||
2
jGui
2
jGui
Submodule jGui updated: 8019dfd11a...af54ecf972
@@ -20,6 +20,7 @@ buildscript {
|
|||||||
name = "sonatype"
|
name = "sonatype"
|
||||||
url = "https://oss.sonatype.org/content/repositories/snapshots/"
|
url = "https://oss.sonatype.org/content/repositories/snapshots/"
|
||||||
}
|
}
|
||||||
|
maven { url 'https://jitpack.io' }
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@@ -41,13 +42,20 @@ buildscript {
|
|||||||
mcVersion >= 10710 ? '1.2-SNAPSHOT' :
|
mcVersion >= 10710 ? '1.2-SNAPSHOT' :
|
||||||
'invalid'
|
'invalid'
|
||||||
)
|
)
|
||||||
|
classpath 'com.github.replaymod:preprocessor:3654e32'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
import com.replaymod.gradle.preprocess.PreprocessTask
|
||||||
|
|
||||||
def mcVersionStr = "${(int)(mcVersion/10000)}.${(int)(mcVersion/100)%100}" + (mcVersion%100==0 ? '' : ".${mcVersion%100}")
|
def mcVersionStr = "${(int)(mcVersion/10000)}.${(int)(mcVersion/100)%100}" + (mcVersion%100==0 ? '' : ".${mcVersion%100}")
|
||||||
|
|
||||||
def FG3 = mcVersion >= 11300
|
def FG3 = mcVersion >= 11300
|
||||||
|
|
||||||
|
def jGuiVersion = project.name
|
||||||
|
if (['1.10.2', '1.11', '1.11.2'].contains(jGuiVersion)) jGuiVersion = '1.9.4'
|
||||||
|
if (['1.12.1', '1.12.2'].contains(jGuiVersion)) jGuiVersion = '1.12'
|
||||||
|
|
||||||
if (mcVersion >= 10800) {
|
if (mcVersion >= 10800) {
|
||||||
apply plugin: 'com.github.johnrengelman.shadow'
|
apply plugin: 'com.github.johnrengelman.shadow'
|
||||||
|
|
||||||
@@ -70,6 +78,8 @@ if (mcVersion >= 10800) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
apply plugin: 'com.replaymod.preprocess'
|
||||||
|
|
||||||
sourceCompatibility = 1.8
|
sourceCompatibility = 1.8
|
||||||
targetCompatibility = 1.8
|
targetCompatibility = 1.8
|
||||||
|
|
||||||
@@ -204,9 +214,6 @@ dependencies {
|
|||||||
if (studioVersion == '1.8.9') studioVersion = '1.8'
|
if (studioVersion == '1.8.9') studioVersion = '1.8'
|
||||||
shadow "com.github.ReplayMod.ReplayStudio:$studioVersion:04a929c", shadeExclusions
|
shadow "com.github.ReplayMod.ReplayStudio:$studioVersion:04a929c", shadeExclusions
|
||||||
|
|
||||||
def jGuiVersion = project.name
|
|
||||||
if (['1.10.2', '1.11', '1.11.2'].contains(jGuiVersion)) jGuiVersion = '1.9.4'
|
|
||||||
if (['1.12.1', '1.12.2'].contains(jGuiVersion)) jGuiVersion = '1.12'
|
|
||||||
shadowReobf(project(":jGui:$jGuiVersion")){
|
shadowReobf(project(":jGui:$jGuiVersion")){
|
||||||
transitive = false // FG 1.2 puts all MC deps into the compile configuration and we don't want to shade those
|
transitive = false // FG 1.2 puts all MC deps into the compile configuration and we don't want to shade those
|
||||||
exclude group: 'org.projectlombok', module: 'lombok' // runtime only for @SneakyThrows which isn't used
|
exclude group: 'org.projectlombok', module: 'lombok' // runtime only for @SneakyThrows which isn't used
|
||||||
@@ -243,42 +250,15 @@ if (mcVersion <= 10710) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (project.name != 'core') {
|
if (project.name != 'core') {
|
||||||
apply from: '../preprocessor.gradle'
|
|
||||||
|
|
||||||
def preprocessedSrc = 'build/preprocessed/src'
|
|
||||||
def preprocessedRes = 'build/preprocessed/res'
|
def preprocessedRes = 'build/preprocessed/res'
|
||||||
def preprocessedAT = 'build/preprocessed/at.cfg'
|
def preprocessedAT = 'build/preprocessed/at.cfg'
|
||||||
def originalSrc = '../../src/main/java'
|
|
||||||
def originalRes = '../../src/main/resources'
|
def originalRes = '../../src/main/resources'
|
||||||
def originalAT = originalRes + '/META-INF/replaymod_at.cfg'
|
def originalAT = originalRes + '/META-INF/replaymod_at.cfg'
|
||||||
def vars = [MC: mcVersion as int]
|
def vars = [MC: mcVersion as int]
|
||||||
|
|
||||||
sourceSets {
|
|
||||||
main.java.srcDir preprocessedSrc
|
|
||||||
main.resources.srcDir preprocessedRes
|
|
||||||
}
|
|
||||||
|
|
||||||
task preprocessJava {
|
|
||||||
inputs.dir(originalSrc)
|
|
||||||
outputs.dir(preprocessedSrc)
|
|
||||||
doLast {
|
|
||||||
project.convertTree(vars, originalSrc, preprocessedSrc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task preprocessResources {
|
|
||||||
inputs.dir(originalRes)
|
|
||||||
outputs.dir(preprocessedRes)
|
|
||||||
doLast {
|
|
||||||
project.convertTree(vars, originalRes, preprocessedRes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
compileJava.dependsOn preprocessJava
|
|
||||||
processResources.dependsOn preprocessResources
|
|
||||||
if (FG3) {
|
if (FG3) {
|
||||||
// FG3 reads the AT file right after project evaluation, so we need to convert it right now
|
// FG3 reads the AT file right after project evaluation, so we need to convert it right now
|
||||||
project.convertTree(vars, originalAT, preprocessedAT)
|
PreprocessTask.convertFile(PreprocessTask.CFG_KEYWORDS, vars, file(originalAT), file(preprocessedAT))
|
||||||
minecraft.accessTransformers << file(preprocessedAT)
|
minecraft.accessTransformers << file(preprocessedAT)
|
||||||
} else {
|
} else {
|
||||||
(mcVersion >= 10800 ? [deobfMcMCP, deobfMcSRG] : [deobfuscateJar, deobfBinJar]).each { task ->
|
(mcVersion >= 10800 ? [deobfMcMCP, deobfMcSRG] : [deobfuscateJar, deobfBinJar]).each { task ->
|
||||||
@@ -286,14 +266,14 @@ if (project.name != 'core') {
|
|||||||
}
|
}
|
||||||
minecraft.accessTransformer preprocessedRes + '/META-INF/replaymod_at.cfg'
|
minecraft.accessTransformer preprocessedRes + '/META-INF/replaymod_at.cfg'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
project(":jGui:$jGuiVersion").afterEvaluate { jGui ->
|
||||||
|
project.tasks.setCoreVersion.dependsOn jGui.tasks.setCoreVersion
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (FG3) {
|
if (FG3) {
|
||||||
minecraft.accessTransformers << file('../../src/main/resources/META-INF/replaymod_at.cfg')
|
minecraft.accessTransformers << file('../../src/main/resources/META-INF/replaymod_at.cfg')
|
||||||
}
|
}
|
||||||
sourceSets {
|
|
||||||
main.java.srcDirs = ['../../src/main/java']
|
|
||||||
main.resources.srcDirs = ['../../src/main/resources']
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
sourceSets {
|
sourceSets {
|
||||||
main {
|
main {
|
||||||
|
|||||||
@@ -1,171 +0,0 @@
|
|||||||
static def evalVar(vars, String var) {
|
|
||||||
if (var.number) {
|
|
||||||
return var as int
|
|
||||||
} else {
|
|
||||||
return vars[var]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
import java.util.regex.Pattern
|
|
||||||
|
|
||||||
static def evalExpr(vars, String expr) {
|
|
||||||
expr = expr.trim()
|
|
||||||
|
|
||||||
def parts = expr.split(/\|\|/)
|
|
||||||
if (parts.length > 1) {
|
|
||||||
return parts.any { evalExpr(vars, it) }
|
|
||||||
}
|
|
||||||
parts = expr.split(/&&/)
|
|
||||||
if (parts.length > 1) {
|
|
||||||
return !parts.any { !evalExpr(vars, it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
def matcher = Pattern.compile(/(.+)(<=|>=|<|>)(.+)/).matcher(expr)
|
|
||||||
if (matcher.matches()) {
|
|
||||||
def lhs = evalVar(vars, matcher.group(1))
|
|
||||||
def rhs = evalVar(vars, matcher.group(3))
|
|
||||||
switch (matcher.group(2)) {
|
|
||||||
case '>=': return lhs >= rhs
|
|
||||||
case '<=': return lhs <= rhs
|
|
||||||
case '>': return lhs > rhs
|
|
||||||
case '<': return lhs < rhs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static def getIndent(String str) {
|
|
||||||
return str.takeWhile {it == ' '}.length()
|
|
||||||
}
|
|
||||||
|
|
||||||
class ParserException extends RuntimeException {
|
|
||||||
ParserException(String str) {
|
|
||||||
super(str)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static def convertSource(Map<String, String> kws, Map<String, Integer> vars, List<String> lines, String fileName) {
|
|
||||||
def ifStack = []
|
|
||||||
List<Integer> indentStack = []
|
|
||||||
def active = true
|
|
||||||
def n = 0
|
|
||||||
lines = lines.collect { line ->
|
|
||||||
n++
|
|
||||||
def trimmed = line.trim()
|
|
||||||
if (trimmed.startsWith(kws.if)) {
|
|
||||||
def result = evalExpr(vars, trimmed.substring(kws.if.length()))
|
|
||||||
ifStack.push(result)
|
|
||||||
if (result != null) {
|
|
||||||
indentStack.push(getIndent(line))
|
|
||||||
active &= result
|
|
||||||
}
|
|
||||||
} else if (trimmed.startsWith(kws.else)) {
|
|
||||||
if (ifStack.isEmpty()) {
|
|
||||||
throw new ParserException("Unexpected else in line $n of $fileName")
|
|
||||||
}
|
|
||||||
def head = ifStack.pop()
|
|
||||||
if (head != null) {
|
|
||||||
head = !head
|
|
||||||
indentStack.pop()
|
|
||||||
indentStack.push(getIndent(line))
|
|
||||||
}
|
|
||||||
ifStack.push(head)
|
|
||||||
active = true;
|
|
||||||
ifStack.each {
|
|
||||||
if (it != null) {
|
|
||||||
active &= it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (trimmed.startsWith(kws.ifdef)) {
|
|
||||||
def result = vars.containsKey(trimmed.substring(kws.ifdef.length()))
|
|
||||||
ifStack.push(result)
|
|
||||||
indentStack.push(getIndent(line))
|
|
||||||
active &= result
|
|
||||||
} else if (trimmed.startsWith(kws.endif)) {
|
|
||||||
if (ifStack.isEmpty()) {
|
|
||||||
throw new ParserException("Unexpected endif in line $n of $fileName")
|
|
||||||
}
|
|
||||||
def head = ifStack.pop()
|
|
||||||
if (head != null) {
|
|
||||||
indentStack.pop()
|
|
||||||
active = true;
|
|
||||||
ifStack.each {
|
|
||||||
if (it != null) {
|
|
||||||
active &= it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (active) {
|
|
||||||
if (trimmed.startsWith(kws.eval)) {
|
|
||||||
line = line.replaceFirst(Pattern.quote(kws.eval) + ' ?', '')
|
|
||||||
if (line.trim().isEmpty()) {
|
|
||||||
line = ''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
def currIndent = indentStack.last()
|
|
||||||
if (trimmed.isEmpty()) {
|
|
||||||
line = ' ' * currIndent + kws.eval
|
|
||||||
} else if (!trimmed.startsWith(kws.eval)) {
|
|
||||||
def actualIndent = getIndent(line)
|
|
||||||
if (currIndent <= actualIndent) {
|
|
||||||
line = ' ' * currIndent + kws.eval + ' ' + line.substring(currIndent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
line
|
|
||||||
}
|
|
||||||
if (!ifStack.isEmpty()) {
|
|
||||||
throw new ParserException("Missing endif in $fileName")
|
|
||||||
}
|
|
||||||
return lines
|
|
||||||
}
|
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets
|
|
||||||
|
|
||||||
static def convertFile(Map<String, String> kws, Map<String, Integer> vars, File inFile, File outFile) {
|
|
||||||
def string = new String(inFile.readBytes(), StandardCharsets.UTF_8)
|
|
||||||
def lines = string.readLines()
|
|
||||||
try {
|
|
||||||
lines = convertSource(kws, vars, lines, inFile.path)
|
|
||||||
} catch (e) {
|
|
||||||
if (e instanceof ParserException) {
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
throw new RuntimeException("Failed to convert file " + inFile, e)
|
|
||||||
}
|
|
||||||
outFile.parentFile.mkdirs()
|
|
||||||
if (string.endsWith('\n')) {
|
|
||||||
outFile.write(lines.collect { it + '\n' }.join(''))
|
|
||||||
} else {
|
|
||||||
outFile.write(lines.join('\n'))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
project.ext.convertTree = { Map<String, Integer> vars, String inName, String outName=inName ->
|
|
||||||
def defaultKws = [if: '//#if ', ifdef: '//#ifdef ', else: '//#else', endif: '//#endif', eval: '//$$']
|
|
||||||
def cfgKws = [if: '##if ', ifdef: '##ifdef ', else: '##else', endif: '##endif', eval: '#$$']
|
|
||||||
def extensions = [
|
|
||||||
'.java': defaultKws,
|
|
||||||
'.gradle': defaultKws,
|
|
||||||
'.json': defaultKws,
|
|
||||||
'.mcmeta': defaultKws,
|
|
||||||
'.cfg': cfgKws
|
|
||||||
]
|
|
||||||
def inPath = project.file(inName).toPath()
|
|
||||||
def outPath = project.file(outName).toPath()
|
|
||||||
def inPlace = inPath.toAbsolutePath().equals(outPath.toAbsolutePath())
|
|
||||||
project.fileTree(inName).forEach { file ->
|
|
||||||
def outFile = outPath.resolve(inPath.relativize(file.toPath())).toFile()
|
|
||||||
def kws = extensions.find { ext, _ -> file.name.endsWith(ext) }
|
|
||||||
if (kws) {
|
|
||||||
convertFile(kws.value, vars, file, outFile)
|
|
||||||
} else if (!inPlace) {
|
|
||||||
copy {
|
|
||||||
from file
|
|
||||||
into outFile.parentFile
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user