Add checks in deserialization code

Signed-off-by: Glease <4586901+Glease@users.noreply.github.com>
This commit is contained in:
Glease committed 2022-03-27 20:07:08 +08:00
1 parent 70e34b9265
commit d0f0e8225b
12 files changed
+485 -114

No files matched your search

+19
View File
@@ -0,0 +1,19 @@
# This is the universal Text Editor Configuration
# for all GTNewHorizons projects
# See: https://editorconfig.org/
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.{bat,ini}]
end_of_line = crlf
[*.{dtd,json,info,mcmeta,md,sh,svg,xml,xsd,xsl,yaml,yml}]
indent_size = 2
-9
View File
@@ -1,9 +0,0 @@
directory="run/crash-reports"
if [ -d $directory ]; then
echo "Crash reports detected:"
cat $directory/*
exit 1
else
echo "No crash reports detected"
exit 0
fi
+51
View File
@@ -0,0 +1,51 @@
#!/usr/bin/env bash
# bashsupport disable=BP5006 # Global environment variables
RUNDIR="run" \
CRASH="crash-reports" \
SERVERLOG="server.log"
# enable nullglob to get 0 results when no match rather than the pattern
shopt -s nullglob
# store matches in array
crash_reports=("$RUNDIR/$CRASH/crash"*.txt)
# if array not empty there are crash_reports
if [ "${#crash_reports[@]}" -gt 0 ]; then
# get the latest crash_report from array
latest_crash_report="${crash_reports[-1]}"
{
printf 'Latest crash report detected %s:\n' "${latest_crash_report##*/}"
cat "$latest_crash_report"
} >&2
exit 1
fi
if grep --quiet --fixed-strings 'Fatal errors were detected' "$SERVERLOG"; then
{
printf 'Fatal errors detected:\n'
cat server.log
} >&2
exit 1
fi
if grep --quiet --fixed-strings 'The state engine was in incorrect state ERRORED and forced into state SERVER_STOPPED' \
"$SERVERLOG"; then
{
printf 'Server force stopped:'
cat server.log
} >&2
exit 1
fi
if ! grep --quiet --perl-regexp --only-matching '.+Done \(.+\)\! For help, type "help" or "\?"' "$SERVERLOG"; then
{
printf 'Server did not finish startup:'
cat server.log
} >&2
exit 1
fi
printf 'No crash reports detected'
exit 0
+10 -10
View File
@@ -14,32 +14,32 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Set up JDK 8 - name: Set up JDK 8
uses: actions/setup-java@v2 uses: actions/setup-java@v2
with: with:
java-version: '8' java-version: '8'
distribution: 'adopt' distribution: 'adopt'
cache: gradle cache: gradle
- name: Grant execute permission for gradlew - name: Grant execute permission for gradlew
run: chmod +x gradlew run: chmod +x gradlew
- name: Setup the workspace - name: Setup the workspace
run: ./gradlew setupCIWorkspace run: ./gradlew setupCIWorkspace
- name: Build the mod - name: Build the mod
run: ./gradlew build run: ./gradlew build
- name: Run server for 1 minute - name: Run server for 1.5 minutes
run: | run: |
mkdir run mkdir run
echo "eula=true" > run/eula.txt echo "eula=true" > run/eula.txt
timeout 10 ./gradlew runServer || true timeout 90 ./gradlew runServer 2>&1 | tee -a server.log || true
- name: Test no crashes happend - name: Test no errors reported during server run
run: | run: |
chmod +x .github/scripts/test-no-crash-reports.sh chmod +x .github/scripts/test_no_error_reports
.github/scripts/test-no-crash-reports.sh .github/scripts/test_no_error_reports
+244 -91
View File
@@ -1,50 +1,64 @@
//version: 1642484596 //version: 1646409286
/* /*
DO NOT CHANGE THIS FILE! DO NOT CHANGE THIS FILE!
Also, you may replace this file at any time if there is an update available. Also, you may replace this file at any time if there is an update available.
Please check https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/main/build.gradle for updates. Please check https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/main/build.gradle for updates.
*/ */
import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.gradle.internal.logging.text.StyledTextOutput.Style
import org.gradle.internal.logging.text.StyledTextOutputFactory
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
buildscript { buildscript {
repositories { repositories {
maven { maven {
name = "forge" name 'forge'
url = "https://maven.minecraftforge.net" url 'https://maven.minecraftforge.net'
} }
maven { maven {
name = "sonatype" name 'sonatype'
url = "https://oss.sonatype.org/content/repositories/snapshots/" url 'https://oss.sonatype.org/content/repositories/snapshots/'
} }
maven { maven {
name = "Scala CI dependencies" name 'Scala CI dependencies'
url = "https://repo1.maven.org/maven2/" url 'https://repo1.maven.org/maven2/'
} }
maven { maven {
name = "jitpack" name 'jitpack'
url = "https://jitpack.io" url 'https://jitpack.io'
} }
} }
dependencies { dependencies {
classpath 'com.github.GTNewHorizons:ForgeGradle:1.2.5' classpath 'com.github.GTNewHorizons:ForgeGradle:1.2.7'
} }
} }
plugins { plugins {
id 'java-library'
id 'idea' id 'idea'
id 'eclipse'
id 'scala' id 'scala'
id("org.ajoberstar.grgit") version("3.1.1") id 'maven-publish'
id("com.github.johnrengelman.shadow") version("4.0.4") id 'org.jetbrains.kotlin.jvm' version '1.5.30' apply false
id("com.palantir.git-version") version("0.12.3") id 'org.jetbrains.kotlin.kapt' version '1.5.30' apply false
id("maven-publish") id 'org.ajoberstar.grgit' version '4.1.1'
id 'com.github.johnrengelman.shadow' version '4.0.4'
id 'com.palantir.git-version' version '0.13.0' apply false
id 'de.undercouch.download' version '5.0.1'
id 'com.github.gmazzo.buildconfig' version '3.0.3' apply false
} }
if (project.file('.git/HEAD').isFile()) {
apply plugin: 'com.palantir.git-version'
}
def out = services.get(StyledTextOutputFactory).create('an-output')
apply plugin: 'forge' apply plugin: 'forge'
def projectJavaVersion = JavaLanguageVersion.of(8) def projectJavaVersion = JavaLanguageVersion.of(8)
@@ -89,27 +103,31 @@ checkPropertyExists("usesShadowedDependencies")
checkPropertyExists("developmentEnvironmentUserName") checkPropertyExists("developmentEnvironmentUserName")
boolean noPublishedSources = project.findProperty("noPublishedSources") ? project.noPublishedSources.toBoolean() : false boolean noPublishedSources = project.findProperty("noPublishedSources") ? project.noPublishedSources.toBoolean() : false
boolean usesMixinDebug = project.findProperty('usesMixinDebug') ?: project.usesMixins.toBoolean()
String javaSourceDir = "src/main/java/" String javaSourceDir = "src/main/java/"
String scalaSourceDir = "src/main/scala/" String scalaSourceDir = "src/main/scala/"
String kotlinSourceDir = "src/main/kotlin/"
String targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") String targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/")
String targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") String targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/")
if((getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists()) == false) { String targetPackageKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/")
throw new GradleException("Could not resolve \"modGroup\"! Could not find " + targetPackageJava + " or " + targetPackageScala) if(!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) {
throw new GradleException("Could not resolve \"modGroup\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin)
} }
if(apiPackage) { if(apiPackage) {
targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/")
targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/")
if((getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists()) == false) { targetPackageKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/")
throw new GradleException("Could not resolve \"apiPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala) if(!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) {
throw new GradleException("Could not resolve \"apiPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin)
} }
} }
if(accessTransformersFile) { if(accessTransformersFile) {
String targetFile = "src/main/resources/META-INF/" + accessTransformersFile String targetFile = "src/main/resources/META-INF/" + accessTransformersFile
if(getFile(targetFile).exists() == false) { if(!getFile(targetFile).exists()) {
throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile) throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile)
} }
} }
@@ -121,15 +139,17 @@ if(usesMixins.toBoolean()) {
targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/")
targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/")
if((getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists()) == false) { targetPackageKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/")
throw new GradleException("Could not resolve \"mixinsPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala) if(!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) {
throw new GradleException("Could not resolve \"mixinsPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin)
} }
String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java" String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java"
String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".scala" String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".scala"
String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java" String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java"
if((getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists()) == false) { String targetFileKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".kt"
throw new GradleException("Could not resolve \"mixinPlugin\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava) if(!(getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists() || getFile(targetFileKotlin).exists())) {
throw new GradleException("Could not resolve \"mixinPlugin\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava + " or " + targetFileKotlin)
} }
} }
@@ -137,8 +157,9 @@ if(coreModClass) {
String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java" String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java"
String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".scala" String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".scala"
String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java" String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java"
if((getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists()) == false) { String targetFileKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".kt"
throw new GradleException("Could not resolve \"coreModClass\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava) if(!(getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists() || getFile(targetFileKotlin).exists())) {
throw new GradleException("Could not resolve \"coreModClass\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava + " or " + targetFileKotlin)
} }
} }
@@ -151,17 +172,35 @@ configurations.all {
} }
// Fix Jenkins' Git: chmod a file should not be detected as a change and append a '.dirty' to the version // Fix Jenkins' Git: chmod a file should not be detected as a change and append a '.dirty' to the version
'git config core.fileMode false'.execute() try {
'git config core.fileMode false'.execute()
}
catch (Exception ignored) {
out.style(Style.Failure).println("git isn't installed at all")
}
// Pulls version first from the VERSION env and then git tag // Pulls version first from the VERSION env and then git tag
String identifiedVersion String identifiedVersion
String versionOverride = System.getenv("VERSION") ?: null
try { try {
String versionOverride = System.getenv("VERSION") ?: null
identifiedVersion = versionOverride == null ? gitVersion() : versionOverride identifiedVersion = versionOverride == null ? gitVersion() : versionOverride
version = minecraftVersion + "-" + identifiedVersion
} }
catch (Exception e) { catch (Exception ignored) {
throw new IllegalStateException("This mod must be version controlled by Git AND the repository must provide at least one tag, or the VERSION override must be set!"); out.style(Style.Failure).text(
'This mod must be version controlled by Git AND the repository must provide at least one tag,\n' +
'or the VERSION override must be set! ').style(Style.SuccessHeader).text('(Do NOT download from GitHub using the ZIP option, instead\n' +
'clone the repository, see ').style(Style.Info).text('https://gtnh.miraheze.org/wiki/Development').style(Style.SuccessHeader).println(' for details.)'
)
versionOverride = 'NO-GIT-TAG-SET'
identifiedVersion = versionOverride
}
version = minecraftVersion + '-' + identifiedVersion
ext {
modVersion = identifiedVersion
}
if(identifiedVersion == versionOverride) {
out.style(Style.Failure).text('Override version to ').style(Style.Identifier).text(modVersion).style(Style.Failure).println('!\7')
} }
group = modGroup group = modGroup
@@ -172,9 +211,25 @@ else {
archivesBaseName = modId archivesBaseName = modId
} }
def arguments = []
def jvmArguments = []
if (usesMixins.toBoolean()) {
arguments += [
"--tweakClass org.spongepowered.asm.launch.MixinTweaker"
]
if (usesMixinDebug.toBoolean()) {
jvmArguments += [
"-Dmixin.debug.countInjections=true",
"-Dmixin.debug.verbose=true",
"-Dmixin.debug.export=true"
]
}
}
minecraft { minecraft {
version = minecraftVersion + "-" + forgeVersion + "-" + minecraftVersion version = minecraftVersion + '-' + forgeVersion + '-' + minecraftVersion
runDir = "run" runDir = 'run'
if (replaceGradleTokenInFile) { if (replaceGradleTokenInFile) {
replaceIn replaceGradleTokenInFile replaceIn replaceGradleTokenInFile
@@ -185,16 +240,30 @@ minecraft {
replace gradleTokenModName, modName replace gradleTokenModName, modName
} }
if(gradleTokenVersion) { if(gradleTokenVersion) {
replace gradleTokenVersion, versionDetails().lastTag replace gradleTokenVersion, modVersion
} }
if(gradleTokenGroupName) { if(gradleTokenGroupName) {
replace gradleTokenGroupName, modGroup replace gradleTokenGroupName, modGroup
} }
} }
clientIntellijRun {
args(arguments)
jvmArgs(jvmArguments)
if(developmentEnvironmentUserName) {
args("--username", developmentEnvironmentUserName)
}
}
serverIntellijRun {
args(arguments)
jvmArgs(jvmArguments)
}
} }
if(file("addon.gradle").exists()) { if(file('addon.gradle').exists()) {
apply from: "addon.gradle" apply from: 'addon.gradle'
} }
apply from: 'repositories.gradle' apply from: 'repositories.gradle'
@@ -207,58 +276,63 @@ configurations {
repositories { repositories {
maven { maven {
name = "Overmind forge repo mirror" name 'Overmind forge repo mirror'
url = "https://gregtech.overminddl1.com/" url 'https://gregtech.overminddl1.com/'
} }
if(usesMixins.toBoolean()) { if(usesMixins.toBoolean()) {
maven { maven {
name = "sponge" name 'sponge'
url = "https://repo.spongepowered.org/repository/maven-public" url 'https://repo.spongepowered.org/repository/maven-public'
} }
maven { maven {
url = "https://jitpack.io" url 'https://jitpack.io'
} }
} }
} }
dependencies { dependencies {
if(usesMixins.toBoolean()) { if(usesMixins.toBoolean()) {
annotationProcessor("org.ow2.asm:asm-debug-all:5.0.3") annotationProcessor('org.ow2.asm:asm-debug-all:5.0.3')
annotationProcessor("com.google.guava:guava:24.1.1-jre") annotationProcessor('com.google.guava:guava:24.1.1-jre')
annotationProcessor("com.google.code.gson:gson:2.8.6") annotationProcessor('com.google.code.gson:gson:2.8.6')
annotationProcessor("org.spongepowered:mixin:0.8-SNAPSHOT") annotationProcessor('org.spongepowered:mixin:0.8-SNAPSHOT')
// using 0.8 to workaround a issue in 0.7 which fails mixin application // using 0.8 to workaround a issue in 0.7 which fails mixin application
compile("com.github.GTNewHorizons:SpongePoweredMixin:0.7.12-GTNH") { compile('com.github.GTNewHorizons:SpongePoweredMixin:0.7.12-GTNH') {
// Mixin includes a lot of dependencies that are too up-to-date // Mixin includes a lot of dependencies that are too up-to-date
exclude module: "launchwrapper" exclude module: 'launchwrapper'
exclude module: "guava" exclude module: 'guava'
exclude module: "gson" exclude module: 'gson'
exclude module: "commons-io" exclude module: 'commons-io'
exclude module: "log4j-core" exclude module: 'log4j-core'
} }
compile("com.github.GTNewHorizons:SpongeMixins:1.5.0") compile('com.github.GTNewHorizons:SpongeMixins:1.5.0')
} }
} }
apply from: 'dependencies.gradle' apply from: 'dependencies.gradle'
def mixingConfigRefMap = "mixins." + modId + ".refmap.json" def mixingConfigRefMap = 'mixins.' + modId + '.refmap.json'
def refMap = "${tasks.compileJava.temporaryDir}" + File.separator + mixingConfigRefMap def refMap = "${tasks.compileJava.temporaryDir}" + File.separator + mixingConfigRefMap
def mixinSrg = "${tasks.reobf.temporaryDir}" + File.separator + "mixins.srg" def mixinSrg = "${tasks.reobf.temporaryDir}" + File.separator + "mixins.srg"
task generateAssets { task generateAssets {
if(usesMixins.toBoolean()) { if (usesMixins.toBoolean()) {
getFile("/src/main/resources/mixins." + modId + ".json").text = """{ def mixinConfigFile = getFile("/src/main/resources/mixins." + modId + ".json");
if (!mixinConfigFile.exists()) {
mixinConfigFile.text = """{
"required": true, "required": true,
"minVersion": "0.7.11", "minVersion": "0.7.11",
"package": "${modGroup}.${mixinsPackage}", "package": "${modGroup}.${mixinsPackage}",
"plugin": "${modGroup}.${mixinPlugin}", "plugin": "${modGroup}.${mixinPlugin}",
"refmap": "${mixingConfigRefMap}", "refmap": "${mixingConfigRefMap}",
"target": "@env(DEFAULT)", "target": "@env(DEFAULT)",
"compatibilityLevel": "JAVA_8" "compatibilityLevel": "JAVA_8",
"mixins": [],
"client": [],
"server": []
} }
""" """
}
} }
} }
@@ -322,15 +396,6 @@ afterEvaluate {
} }
runClient { runClient {
def arguments = []
if(usesMixins.toBoolean()) {
arguments += [
"--mods=../build/libs/$modId-${version}.jar",
"--tweakClass org.spongepowered.asm.launch.MixinTweaker"
]
}
if(developmentEnvironmentUserName) { if(developmentEnvironmentUserName) {
arguments += [ arguments += [
"--username", "--username",
@@ -339,19 +404,12 @@ runClient {
} }
args(arguments) args(arguments)
jvmArgs(jvmArguments)
} }
runServer { runServer {
def arguments = []
if (usesMixins.toBoolean()) {
arguments += [
"--mods=../build/libs/$modId-${version}.jar",
"--tweakClass org.spongepowered.asm.launch.MixinTweaker"
]
}
args(arguments) args(arguments)
jvmArgs(jvmArguments)
} }
tasks.withType(JavaExec).configureEach { tasks.withType(JavaExec).configureEach {
@@ -362,8 +420,7 @@ tasks.withType(JavaExec).configureEach {
) )
} }
processResources processResources {
{
// this will ensure that this task is redone when the versions change. // this will ensure that this task is redone when the versions change.
inputs.property "version", project.version inputs.property "version", project.version
inputs.property "mcversion", project.minecraft.version inputs.property "mcversion", project.minecraft.version
@@ -372,18 +429,18 @@ processResources
from(sourceSets.main.resources.srcDirs) { from(sourceSets.main.resources.srcDirs) {
include 'mcmod.info' include 'mcmod.info'
// replace version and mcversion // replace modVersion and minecraftVersion
expand "minecraftVersion": project.minecraft.version, expand "minecraftVersion": project.minecraft.version,
"modVersion": versionDetails().lastTag, "modVersion": modVersion,
"modId": modId, "modId": modId,
"modName": modName "modName": modName
} }
if(usesMixins.toBoolean()) { if(usesMixins.toBoolean()) {
from refMap from refMap
} }
// copy everything else, thats not the mcmod.info // copy everything else that's not the mcmod.info
from(sourceSets.main.resources.srcDirs) { from(sourceSets.main.resources.srcDirs) {
exclude 'mcmod.info' exclude 'mcmod.info'
} }
@@ -391,7 +448,7 @@ processResources
def getManifestAttributes() { def getManifestAttributes() {
def manifestAttributes = [:] def manifestAttributes = [:]
if(containsMixinsAndOrCoreModOnly.toBoolean() == false && (usesMixins.toBoolean() || coreModClass)) { if(!containsMixinsAndOrCoreModOnly.toBoolean() && (usesMixins.toBoolean() || coreModClass)) {
manifestAttributes += ["FMLCorePluginContainsFMLMod": true] manifestAttributes += ["FMLCorePluginContainsFMLMod": true]
} }
@@ -407,14 +464,14 @@ def getManifestAttributes() {
manifestAttributes += [ manifestAttributes += [
"TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker",
"MixinConfigs" : "mixins." + modId + ".json", "MixinConfigs" : "mixins." + modId + ".json",
"ForceLoadAsMod" : containsMixinsAndOrCoreModOnly.toBoolean() == false "ForceLoadAsMod" : !containsMixinsAndOrCoreModOnly.toBoolean()
] ]
} }
return manifestAttributes return manifestAttributes
} }
task sourcesJar(type: Jar) { task sourcesJar(type: Jar) {
from (sourceSets.main.allJava) from (sourceSets.main.allSource)
from (file("$projectDir/LICENSE")) from (file("$projectDir/LICENSE"))
getArchiveClassifier().set('sources') getArchiveClassifier().set('sources')
} }
@@ -469,7 +526,7 @@ task devJar(type: Jar) {
} }
task apiJar(type: Jar) { task apiJar(type: Jar) {
from (sourceSets.main.allJava) { from (sourceSets.main.allSource) {
include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**' include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**'
} }
@@ -494,11 +551,22 @@ artifacts {
} }
} }
// publishing // The gradle metadata includes all of the additional deps that we disabled from POM generation (including forgeBin with no groupID),
// and isn't strictly needed with the POM so just disable it.
tasks.withType(GenerateModuleMetadata) {
enabled = false
}
// workaround variable hiding in pom processing
def projectConfigs = project.configurations
publishing { publishing {
publications { publications {
maven(MavenPublication) { maven(MavenPublication) {
artifact source: usesShadowedDependencies.toBoolean() ? shadowJar : jar, classifier: "" from components.java
if(usesShadowedDependencies.toBoolean()) {
artifact source: shadowJar, classifier: ""
}
if(!noPublishedSources) { if(!noPublishedSources) {
artifact source: sourcesJar, classifier: "src" artifact source: sourcesJar, classifier: "src"
} }
@@ -511,6 +579,25 @@ publishing {
artifactId = System.getenv("ARTIFACT_ID") ?: project.name artifactId = System.getenv("ARTIFACT_ID") ?: project.name
// Using the identified version, not project.version as it has the prepended 1.7.10 // Using the identified version, not project.version as it has the prepended 1.7.10
version = System.getenv("RELEASE_VERSION") ?: identifiedVersion version = System.getenv("RELEASE_VERSION") ?: identifiedVersion
// remove extra garbage from minecraft and minecraftDeps configuration
pom.withXml {
def badArtifacts = [:].withDefault {[] as Set<String>}
for (configuration in [projectConfigs.minecraft, projectConfigs.minecraftDeps]) {
for (dependency in configuration.allDependencies) {
badArtifacts[dependency.group == null ? "" : dependency.group] += dependency.name
}
}
// example for specifying extra stuff to ignore
// badArtifacts["org.example.group"] += "artifactName"
Node pomNode = asNode()
pomNode.dependencies.'*'.findAll() {
badArtifacts[it.groupId.text()].contains(it.artifactId.text())
}.each() {
it.parent().remove(it)
}
}
} }
} }
@@ -538,7 +625,7 @@ if (isNewBuildScriptVersionAvailable(projectDir.toString())) {
if (autoUpdateBuildScript.toBoolean()) { if (autoUpdateBuildScript.toBoolean()) {
performBuildScriptUpdate(projectDir.toString()) performBuildScriptUpdate(projectDir.toString())
} else { } else {
println("Build script update available! Run 'gradle updateBuildScript'") out.style(Style.SuccessHeader).println("Build script update available! Run 'gradle updateBuildScript'")
} }
} }
@@ -550,7 +637,7 @@ boolean performBuildScriptUpdate(String projectDir) {
if (isNewBuildScriptVersionAvailable(projectDir)) { if (isNewBuildScriptVersionAvailable(projectDir)) {
def buildscriptFile = getFile("build.gradle") def buildscriptFile = getFile("build.gradle")
availableBuildScriptUrl().withInputStream { i -> buildscriptFile.withOutputStream { it << i } } availableBuildScriptUrl().withInputStream { i -> buildscriptFile.withOutputStream { it << i } }
print("Build script updated. Please REIMPORT the project or RESTART your IDE!") out.style(Style.Success).print("Build script updated. Please REIMPORT the project or RESTART your IDE!")
return true return true
} }
return false return false
@@ -581,10 +668,76 @@ configure(updateBuildScript) {
description = 'Updates the build script to the latest version' description = 'Updates the build script to the latest version'
} }
// Deobfuscation
def deobf(String sourceURL) {
try {
URL url = new URL(sourceURL)
String fileName = url.getFile()
//get rid of directories:
int lastSlash = fileName.lastIndexOf("/")
if(lastSlash > 0) {
fileName = fileName.substring(lastSlash + 1)
}
//get rid of extension:
if(fileName.endsWith(".jar")) {
fileName = fileName.substring(0, fileName.lastIndexOf("."))
}
String hostName = url.getHost()
if(hostName.startsWith("www.")) {
hostName = hostName.substring(4)
}
List parts = Arrays.asList(hostName.split("\\."))
Collections.reverse(parts)
hostName = String.join(".", parts)
return deobf(sourceURL, hostName + "/" + fileName)
} catch(Exception e) {
return deobf(sourceURL, "deobf/" + String.valueOf(sourceURL.hashCode()))
}
}
// The method above is to be preferred. Use this method if the filename is not at the end of the URL.
def deobf(String sourceURL, String fileName) {
String cacheDir = System.getProperty("user.home") + "/.gradle/caches/"
String bon2Dir = cacheDir + "forge_gradle/deobf"
String bon2File = bon2Dir + "/BON2-2.5.0.jar"
String obfFile = cacheDir + "modules-2/files-2.1/" + fileName + ".jar"
String deobfFile = cacheDir + "modules-2/files-2.1/" + fileName + "-deobf.jar"
if(file(deobfFile).exists()) {
return files(deobfFile)
}
download.run {
src 'https://github.com/GTNewHorizons/BON2/releases/download/2.5.0/BON2-2.5.0.CUSTOM-all.jar'
dest bon2File
quiet true
overwrite false
}
download.run {
src sourceURL
dest obfFile
quiet true
overwrite false
}
exec {
commandLine 'java', '-jar', bon2File, '--inputJar', obfFile, '--outputJar', deobfFile, '--mcVer', '1.7.10', '--mappingsVer', 'stable_12', '--notch'
workingDir bon2Dir
standardOutput = new ByteArrayOutputStream()
}
return files(deobfFile)
}
// Helper methods // Helper methods
def checkPropertyExists(String propertyName) { def checkPropertyExists(String propertyName) {
if (project.hasProperty(propertyName) == false) { if (!project.hasProperty(propertyName)) {
throw new GradleException("This project requires a property \"" + propertyName + "\"! Please add it your \"gradle.properties\". You can find all properties and their description here: https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/main/gradle.properties") throw new GradleException("This project requires a property \"" + propertyName + "\"! Please add it your \"gradle.properties\". You can find all properties and their description here: https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/main/gradle.properties")
} }
} }
@@ -0,0 +1 @@
net-filter.cfg
@@ -0,0 +1,7 @@
cfg messageWhitelist {
exact = =[
]
prefix = =[
]
enforce = yes
}
+12 -1
View File
@@ -12,14 +12,19 @@ package net.bdew.lib
import cpw.mods.fml.common.Mod.EventHandler import cpw.mods.fml.common.Mod.EventHandler
import cpw.mods.fml.common.event.{FMLPreInitializationEvent, FMLServerStartingEvent, FMLServerStoppingEvent} import cpw.mods.fml.common.event.{FMLPreInitializationEvent, FMLServerStartingEvent, FMLServerStoppingEvent}
import cpw.mods.fml.common.{FMLCommonHandler, Mod} import cpw.mods.fml.common.{FMLCommonHandler, Mod}
import net.bdew.lib.multiblock.network.NetHandler import net.bdew.lib.multiblock.data.MsgOutputCfgRSMode
import net.bdew.lib.multiblock.network.{MsgOutputCfg, MsgOutputCfgSlot, NetHandler}
import net.bdew.lib.network.{BaseMessage, NetworkSecurityLoader, SerializedMessageCodec}
import net.bdew.lib.tooltip.TooltipHandler import net.bdew.lib.tooltip.TooltipHandler
import net.minecraft.command.CommandHandler import net.minecraft.command.CommandHandler
import org.apache.logging.log4j.Logger import org.apache.logging.log4j.Logger
import java.io.File
@Mod(modid = "bdlib", name = "BD lib", version = "GRADLETOKEN_VERSION", modLanguage = "scala") @Mod(modid = "bdlib", name = "BD lib", version = "GRADLETOKEN_VERSION", modLanguage = "scala")
object BdLib { object BdLib {
var log: Logger = null var log: Logger = null
var configDir: File = null
def logDebug(msg: String, args: Any*) = log.debug(msg.format(args: _*)) def logDebug(msg: String, args: Any*) = log.debug(msg.format(args: _*))
def logInfo(msg: String, args: Any*) = log.info(msg.format(args: _*)) def logInfo(msg: String, args: Any*) = log.info(msg.format(args: _*))
@@ -37,6 +42,12 @@ object BdLib {
log.info("bdlib GRADLETOKEN_VERSION loaded") log.info("bdlib GRADLETOKEN_VERSION loaded")
log.debug("List of loaded APIs: " + ApiReporter.APIs) log.debug("List of loaded APIs: " + ApiReporter.APIs)
FMLCommonHandler.instance().registerCrashCallable(ApiReporter) FMLCommonHandler.instance().registerCrashCallable(ApiReporter)
configDir = new File(ev.getModConfigurationDirectory, "bdlib")
SerializedMessageCodec.addValidClass(classOf[BaseMessage[_]])
SerializedMessageCodec.addValidClass(classOf[MsgOutputCfgRSMode])
SerializedMessageCodec.addValidClass(classOf[MsgOutputCfg])
SerializedMessageCodec.addValidClass(classOf[MsgOutputCfgSlot])
NetworkSecurityLoader.loadConfigFiles()
NetHandler.init() NetHandler.init()
if (ev.getSide.isClient) { if (ev.getSide.isClient) {
TooltipHandler.init() TooltipHandler.init()
@@ -0,0 +1,41 @@
package net.bdew.lib.network
import net.bdew.lib.BdLib
import net.bdew.lib.recipes.{RecipeLoader, RecipeParser, RecipesHelper}
import net.bdew.lib.recipes.gencfg.{ConfigSection, GenericConfigLoader, GenericConfigParser}
import java.io.{File, FileWriter}
object NetworkSecurity extends ConfigSection
object NetworkSecurityLoader {
val loader = new RecipeLoader with GenericConfigLoader {
override val cfgStore: ConfigSection = NetworkSecurity
override def newParser(): RecipeParser = new RecipeParser with GenericConfigParser
}
def loadConfigFiles(): Unit = {
if (!BdLib.configDir.exists()) {
BdLib.configDir.mkdir()
val nl = System.getProperty("line.separator")
val f = new FileWriter(new File(BdLib.configDir, "readme.txt"))
f.write("Any .cfg files in this directory will be loaded after the internal configuration, in alphabetic order" + nl)
f.write("Files in 'overrides' directory with matching names cab be used to override internal configuration" + nl)
f.close()
}
RecipesHelper.loadConfigs(
modName = "BdLib",
listResource = "/assets/bdlib/config/files.lst",
configDir = BdLib.configDir,
resBaseName = "/assets/bdlib/config/",
loader = loader)
val section = NetworkSecurity.getSection("messageWhitelist")
SerializedMessageCodec.validClassPrefixes ++= section.getStringList("prefix")
SerializedMessageCodec.validClasses ++= section.getStringList("exact")
SerializedMessageCodec.enforceFilter = section.getBoolean("enforce")
SerializedMessageCodec.validClassCache.clear()
}
}
@@ -9,8 +9,12 @@
package net.bdew.lib.network package net.bdew.lib.network
import java.io.{ObjectInputStream, ObjectOutputStream} import java.io.{ObjectInputStream, ObjectOutputStream, ObjectStreamClass, Serializable}
import java.lang.{Boolean => BoxedBoolean}
import java.util import java.util
import java.util.concurrent.ConcurrentHashMap
import java.util.function.{Function => JavaFunction}
import scala.collection.mutable
import cpw.mods.fml.common.network.NetworkRegistry import cpw.mods.fml.common.network.NetworkRegistry
import cpw.mods.fml.common.network.internal.FMLProxyPacket import cpw.mods.fml.common.network.internal.FMLProxyPacket
@@ -19,6 +23,7 @@ import io.netty.channel.ChannelHandler.Sharable
import io.netty.channel.ChannelHandlerContext import io.netty.channel.ChannelHandlerContext
import io.netty.handler.codec.MessageToMessageCodec import io.netty.handler.codec.MessageToMessageCodec
import net.bdew.lib.BdLib import net.bdew.lib.BdLib
import net.bdew.lib.network.SerializedMessageCodec._
@Sharable @Sharable
class SerializedMessageCodec[T <: NetChannel] extends MessageToMessageCodec[FMLProxyPacket, BaseMessage[T]] { class SerializedMessageCodec[T <: NetChannel] extends MessageToMessageCodec[FMLProxyPacket, BaseMessage[T]] {
@@ -32,10 +37,98 @@ class SerializedMessageCodec[T <: NetChannel] extends MessageToMessageCodec[FMLP
def decode(ctx: ChannelHandlerContext, msg: FMLProxyPacket, out: util.List[AnyRef]) { def decode(ctx: ChannelHandlerContext, msg: FMLProxyPacket, out: util.List[AnyRef]) {
try { try {
val reader = new ObjectInputStream(new ByteBufInputStream(msg.payload())) val reader = new ObjectInputStream(new ByteBufInputStream(msg.payload())) {
override def resolveClass(desc: ObjectStreamClass): Class[_] = {
val name = desc.getName
if (!validClassCache.computeIfAbsent(name, new JavaFunction[String, BoxedBoolean]() {
override def apply(v1: String): BoxedBoolean =
validClasses.contains(v1) || validClassPrefixes.exists(v1.startsWith)
})) {
BdLib.log.warn("Received disallowed message component class: {}", name)
if (enforceFilter) {
throw new InvalidClassException(name)
}
}
super.resolveClass(desc)
}
}
out.add(reader.readObject()) out.add(reader.readObject())
} catch { } catch {
case e: Throwable => BdLib.log.error("Error decoding packet", e) case e: Throwable => BdLib.log.error("Error decoding packet", e)
} }
} }
} }
object SerializedMessageCodec {
/**
* A hardcoded list of possible loaded - and probably safe - classes
*
* Can be extended via configurations
*/
val validClasses: mutable.Set[String] = mutable.Set(
"scala.Enumeration",
"scala.Enumeration$Val",
"scala.Enumeration$Value",
"scala.collection.mutable.HashMap",
"java.lang.Float",
"java.lang.Double",
"java.lang.Integer",
"java.lang.Number",
"net.bdew.lib.multiblock.data.RSMode$",
"net.bdew.lib.network.NBTTagCompoundSerialize",
"net.bdew.lib.network.ItemStackSerialize",
"net.bdew.lib.network.BaseMessage",
"net.bdew.lib.multiblock.data.MsgOutputCfgRSMode",
"net.bdew.lib.multiblock.network.MsgOutputCfg",
"net.bdew.lib.multiblock.network.MsgOutputCfgSlot",
// ae2stuff stuff
"net.bdew.ae2stuff.items.visualiser.VisualisationData",
"net.bdew.ae2stuff.items.visualiser.VisualisationModes$",
"net.bdew.ae2stuff.network.MsgSetLock",
"net.bdew.ae2stuff.network.MsgSetRecipe",
"net.bdew.ae2stuff.network.MsgSetRecipe2",
"net.bdew.ae2stuff.network.MsgSetRecipe3",
"net.bdew.ae2stuff.network.MsgVisualisationData",
"net.bdew.ae2stuff.network.MsgVisualisationMode",
// gendustry
// none
// pressure pipes
"net.minecraftforge.common.util.ForgeDirection",
"net.bdew.pressure.blocks.router.gui.MsgSetRouterSideControl",
"net.bdew.pressure.items.configurator.MsgSetFluidFilter",
"net.bdew.pressure.items.configurator.MsgUnsetFluidFilter",
"net.bdew.pressure.network.MsgTankUpdate",
// advanced generators
"net.bdew.generators.network.PktDumpBuffers"
// add other bdew mods in configurations if you need. this is as far as I'd like to support - glee8e
)
val validClassPrefixes: mutable.Set[String] = mutable.Set()
val validClassCache: ConcurrentHashMap[String, BoxedBoolean] = new ConcurrentHashMap[String, BoxedBoolean]()
var enforceFilter: Boolean = true
def addValidClass(clazz: Class[_]): Unit = {
if (classOf[Serializable].isAssignableFrom(clazz)) {
if (validClasses.add(clazz.getName)) {
// recursively add all superclasses that are also serializable
// only keep adding if class not already added
addValidClass(clazz.getSuperclass)
// recursively add all serialized fields
val desc = ObjectStreamClass.lookup(clazz)
if (desc != null)
desc.getFields.map { it => it.getType }.foreach(SerializedMessageCodec.addValidClass)
}
}
}
}
class InvalidClassException(msg: String) extends ClassNotFoundException(msg)
@@ -21,6 +21,8 @@ case class EntryStr(v: String) extends ConfigEntry
case class EntryNumList(v: List[Double]) extends ConfigEntry case class EntryNumList(v: List[Double]) extends ConfigEntry
case class EntryStrList(v: List[String]) extends ConfigEntry
case class ConfigSection(pfx: String = "") extends ConfigEntry with Iterable[(String, ConfigEntry)] { case class ConfigSection(pfx: String = "") extends ConfigEntry with Iterable[(String, ConfigEntry)] {
var raw = Map.empty[String, ConfigEntry].withDefault(x => sys.error("Config value '%s%s' is missing".format(pfx, x))) var raw = Map.empty[String, ConfigEntry].withDefault(x => sys.error("Config value '%s%s' is missing".format(pfx, x)))
@@ -41,6 +43,7 @@ case class ConfigSection(pfx: String = "") extends ConfigEntry with Iterable[(St
def getDouble(id: String) = getRaw(id, classOf[EntryDouble]).v def getDouble(id: String) = getRaw(id, classOf[EntryDouble]).v
def getString(id: String) = getRaw(id, classOf[EntryStr]).v def getString(id: String) = getRaw(id, classOf[EntryStr]).v
def getStringList(id: String) = getRaw(id, classOf[EntryStrList]).v
def getDoubleList(id: String) = getRaw(id, classOf[EntryNumList]).v def getDoubleList(id: String) = getRaw(id, classOf[EntryNumList]).v
def getSection(id: String) = getRaw(id, classOf[ConfigSection]) def getSection(id: String) = getRaw(id, classOf[ConfigSection])
@@ -24,8 +24,9 @@ trait GenericConfigParser extends RecipeParser {
def cvNum = signedNumber ^^ EntryDouble def cvNum = signedNumber ^^ EntryDouble
def cvStr = str ^^ EntryStr def cvStr = str ^^ EntryStr
def cvNumList = "=" ~> "{" ~> signedNumber.* <~ "}" ^^ EntryNumList def cvNumList = "=" ~> "{" ~> signedNumber.* <~ "}" ^^ EntryNumList
def cvStrList = "=" ~> "[" ~> str.* <~ "]" ^^ EntryStrList
def cfgValue = cvNum | cvStr | cvNumList def cfgValue = cvNum | cvStr | cvNumList | cvStrList
def ceSub = cfgBlock ^^ { case (id, st) => CfgSection(id, st) } def ceSub = cfgBlock ^^ { case (id, st) => CfgSection(id, st) }
def ceAssign = str ~ "=" ~ cfgValue ^^ { case k ~ eq ~ v => CfgVal(k, v) } def ceAssign = str ~ "=" ~ cfgValue ^^ { case k ~ eq ~ v => CfgVal(k, v) }