mirror of
https://github.com/GTNewHorizons/BetterCrashes.git
synced 2026-10-26 14:23:54 +00:00
Update build (#1)
* Switch to GTNH ForgeGradle * spotlessApply * Switch to Sponge Mixin, reformat file names, drop Grimoire dependency * Fix mapping * Workflows * CODEOWNERS * .editorconfig * Update README * updateBuildScript * address review * remove spotless.gradle
This commit is contained in:
1 parent
9b900985a4
commit
96dbab660d
32 files changed
+1580
-266
No files matched your search
@@ -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
|
||||
@@ -0,0 +1,13 @@
|
||||
|
||||
name: Build and test
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ master, main ]
|
||||
push:
|
||||
branches: [ master, main ]
|
||||
|
||||
jobs:
|
||||
build-and-test:
|
||||
uses: GTNewHorizons/GTNH-Actions-Workflows/.github/workflows/build-and-test.yml@master
|
||||
secrets: inherit
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
name: Release tagged build
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: [ '*' ]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
release-tags:
|
||||
uses: GTNewHorizons/GTNH-Actions-Workflows/.github/workflows/release-tags.yml@master
|
||||
secrets: inherit
|
||||
+25
-17
@@ -1,24 +1,32 @@
|
||||
.git
|
||||
.gradle
|
||||
.idea
|
||||
.settings
|
||||
.metadata
|
||||
bin
|
||||
build
|
||||
run
|
||||
minecraft
|
||||
eclipse
|
||||
/.idea/
|
||||
/.vscode/
|
||||
/run/
|
||||
/build/
|
||||
/eclipse/
|
||||
.classpath
|
||||
.project
|
||||
.apt_generated
|
||||
.apt_generated_tests
|
||||
|
||||
*.bat
|
||||
*.sh
|
||||
/bin/
|
||||
/config/
|
||||
/crash-reports/
|
||||
/logs/
|
||||
options.txt
|
||||
/saves/
|
||||
usernamecache.json
|
||||
banned-ips.json
|
||||
banned-players.json
|
||||
eula.txt
|
||||
ops.json
|
||||
server.properties
|
||||
servers.dat
|
||||
usercache.json
|
||||
whitelist.json
|
||||
/out/
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
*.launch
|
||||
.factorypath
|
||||
|
||||
forge*changelog.txt
|
||||
src/main/resources/mixins.*.json
|
||||
*.bat
|
||||
*.DS_Store
|
||||
!gradlew.bat
|
||||
@@ -0,0 +1,2 @@
|
||||
# Any Github changes require admin approval
|
||||
/.github/** @GTNewHorizons/admin
|
||||
@@ -7,11 +7,7 @@ BetterCrashes makes Minecraft return you to the main menu when it crashes,and it
|
||||
|
||||
Most of the code comes from VanillaFix, I just make them work on Minecraft 1.7.10.
|
||||
|
||||
Requires [Grimoire](https://github.com/CrucibleMC/Grimoire) mod to work
|
||||
|
||||
## Known Issues
|
||||
|
||||
Not compatible with hodgepodge mod,you need go to hodgepodge mod's config file to turn off fixGuiGameOver,if you don't do this, it may cause a crash.
|
||||
Requires [SpongeMixins](https://github.com/GTNewHorizons/SpongeMixins) mod to work
|
||||
|
||||
## Credits
|
||||
Thanks VanillaFix and Grimoire
|
||||
Thanks to VanillaFix and original author, vfyjxf
|
||||
+884
-42
@@ -1,81 +1,923 @@
|
||||
//version: 1658080040
|
||||
/*
|
||||
DO NOT CHANGE THIS FILE!
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation
|
||||
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.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipInputStream
|
||||
import java.util.zip.ZipOutputStream
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
|
||||
maven {
|
||||
name = "github"
|
||||
url = "https://github.com/juanmuscaria/maven/raw/master"
|
||||
name 'forge'
|
||||
url 'https://maven.minecraftforge.net'
|
||||
}
|
||||
maven {
|
||||
name 'sonatype'
|
||||
url 'https://oss.sonatype.org/content/repositories/snapshots/'
|
||||
}
|
||||
maven {
|
||||
name 'Scala CI dependencies'
|
||||
url 'https://repo1.maven.org/maven2/'
|
||||
}
|
||||
maven {
|
||||
name 'jitpack'
|
||||
url 'https://jitpack.io'
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'net.minecraftforge.gradle:ForgeGradle:1.2-1.4.0-SNAPSHOT'
|
||||
classpath 'com.integral.grimoire:GrimoireShenanigans:[1.3.0,)'
|
||||
classpath 'com.github.GTNewHorizons:ForgeGradle:1.2.7'
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id 'java-library'
|
||||
id 'idea'
|
||||
id 'eclipse'
|
||||
id 'scala'
|
||||
id 'maven-publish'
|
||||
id 'org.jetbrains.kotlin.jvm' version '1.5.30' apply false
|
||||
id 'org.jetbrains.kotlin.kapt' version '1.5.30' apply false
|
||||
id 'com.google.devtools.ksp' version '1.5.30-1.0.0' apply false
|
||||
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
|
||||
id "com.diffplug.spotless" version "6.7.2"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.diffplug:blowdryer:1.6.0'
|
||||
}
|
||||
|
||||
apply plugin: 'com.diffplug.blowdryer'
|
||||
|
||||
if (project.file('.git/HEAD').isFile()) {
|
||||
apply plugin: 'com.palantir.git-version'
|
||||
}
|
||||
|
||||
def out = services.get(StyledTextOutputFactory).create('an-output')
|
||||
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'forge'
|
||||
apply plugin: 'grimoire-shenanigans'
|
||||
|
||||
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
|
||||
sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8'
|
||||
def projectJavaVersion = JavaLanguageVersion.of(8)
|
||||
|
||||
version = mod_version
|
||||
group = mod_group
|
||||
archivesBaseName = mod_archives_name
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion.set(projectJavaVersion)
|
||||
}
|
||||
}
|
||||
|
||||
idea {
|
||||
module {
|
||||
inheritOutputDirs = true
|
||||
downloadJavadoc = true
|
||||
downloadSources = true
|
||||
}
|
||||
}
|
||||
apply from: Blowdryer.file('spotless.gradle')
|
||||
|
||||
if(JavaVersion.current() != JavaVersion.VERSION_1_8) {
|
||||
throw new GradleException("This project requires Java 8, but it's running on " + JavaVersion.current())
|
||||
}
|
||||
|
||||
checkPropertyExists("modName")
|
||||
checkPropertyExists("modId")
|
||||
checkPropertyExists("modGroup")
|
||||
checkPropertyExists("autoUpdateBuildScript")
|
||||
checkPropertyExists("minecraftVersion")
|
||||
checkPropertyExists("forgeVersion")
|
||||
checkPropertyExists("replaceGradleTokenInFile")
|
||||
checkPropertyExists("gradleTokenModId")
|
||||
checkPropertyExists("gradleTokenModName")
|
||||
checkPropertyExists("gradleTokenVersion")
|
||||
checkPropertyExists("gradleTokenGroupName")
|
||||
checkPropertyExists("apiPackage")
|
||||
checkPropertyExists("accessTransformersFile")
|
||||
checkPropertyExists("usesMixins")
|
||||
checkPropertyExists("mixinPlugin")
|
||||
checkPropertyExists("mixinsPackage")
|
||||
checkPropertyExists("coreModClass")
|
||||
checkPropertyExists("containsMixinsAndOrCoreModOnly")
|
||||
checkPropertyExists("usesShadowedDependencies")
|
||||
checkPropertyExists("developmentEnvironmentUserName")
|
||||
|
||||
boolean noPublishedSources = project.findProperty("noPublishedSources") ? project.noPublishedSources.toBoolean() : false
|
||||
boolean usesMixinDebug = project.findProperty('usesMixinDebug') ?: project.usesMixins.toBoolean()
|
||||
boolean forceEnableMixins = project.findProperty('forceEnableMixins') ? project.forceEnableMixins.toBoolean() : false
|
||||
String channel = project.findProperty('channel') ? project.channel : 'stable'
|
||||
String mappingsVersion = project.findProperty('mappingsVersion') ? project.mappingsVersion : '12'
|
||||
String remoteMappings = project.findProperty('remoteMappings') ? project.remoteMappings : 'https://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/'
|
||||
|
||||
String javaSourceDir = "src/main/java/"
|
||||
String scalaSourceDir = "src/main/scala/"
|
||||
String kotlinSourceDir = "src/main/kotlin/"
|
||||
|
||||
String targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/")
|
||||
String targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/")
|
||||
String targetPackageKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/")
|
||||
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) {
|
||||
targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/")
|
||||
targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/")
|
||||
targetPackageKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/")
|
||||
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) {
|
||||
String targetFile = "src/main/resources/META-INF/" + accessTransformersFile
|
||||
if(!getFile(targetFile).exists()) {
|
||||
throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile)
|
||||
}
|
||||
}
|
||||
|
||||
if(usesMixins.toBoolean()) {
|
||||
if(mixinsPackage.isEmpty() || mixinPlugin.isEmpty()) {
|
||||
throw new GradleException("\"mixinPlugin\" requires \"mixinsPackage\" and \"mixinPlugin\" to be set!")
|
||||
}
|
||||
|
||||
targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/")
|
||||
targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/")
|
||||
targetPackageKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/")
|
||||
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 targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".scala"
|
||||
String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java"
|
||||
String targetFileKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".kt"
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
if(coreModClass) {
|
||||
String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java"
|
||||
String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".scala"
|
||||
String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java"
|
||||
String targetFileKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".kt"
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
configurations.all {
|
||||
resolutionStrategy.cacheChangingModulesFor(0, TimeUnit.SECONDS)
|
||||
|
||||
// Make sure GregTech build won't time out
|
||||
System.setProperty("org.gradle.internal.http.connectionTimeout", 120000 as String)
|
||||
System.setProperty("org.gradle.internal.http.socketTimeout", 120000 as String)
|
||||
}
|
||||
|
||||
// Fix Jenkins' Git: chmod a file should not be detected as a change and append a '.dirty' to the version
|
||||
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
|
||||
String identifiedVersion
|
||||
String versionOverride = System.getenv("VERSION") ?: null
|
||||
try {
|
||||
identifiedVersion = versionOverride == null ? gitVersion() : versionOverride
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
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
|
||||
if(project.hasProperty("customArchiveBaseName") && customArchiveBaseName) {
|
||||
archivesBaseName = customArchiveBaseName
|
||||
}
|
||||
else {
|
||||
archivesBaseName = modId
|
||||
}
|
||||
|
||||
def arguments = []
|
||||
def jvmArguments = []
|
||||
|
||||
if (usesMixins.toBoolean() || forceEnableMixins) {
|
||||
arguments += [
|
||||
"--tweakClass org.spongepowered.asm.launch.MixinTweaker"
|
||||
]
|
||||
if (usesMixinDebug.toBoolean()) {
|
||||
jvmArguments += [
|
||||
"-Dmixin.debug.countInjections=true",
|
||||
"-Dmixin.debug.verbose=true",
|
||||
"-Dmixin.debug.export=true"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
minecraft {
|
||||
version = "1.7.10-10.13.4.1614-1.7.10"
|
||||
runDir = "eclipse"
|
||||
replace "@VERSION@", project.version
|
||||
version = minecraftVersion + '-' + forgeVersion + '-' + minecraftVersion
|
||||
runDir = 'run'
|
||||
|
||||
if (replaceGradleTokenInFile) {
|
||||
replaceIn replaceGradleTokenInFile
|
||||
if(gradleTokenModId) {
|
||||
replace gradleTokenModId, modId
|
||||
}
|
||||
if(gradleTokenModName) {
|
||||
replace gradleTokenModName, modName
|
||||
}
|
||||
if(gradleTokenVersion) {
|
||||
replace gradleTokenVersion, modVersion
|
||||
}
|
||||
if(gradleTokenGroupName) {
|
||||
replace gradleTokenGroupName, modGroup
|
||||
}
|
||||
}
|
||||
|
||||
clientIntellijRun {
|
||||
args(arguments)
|
||||
jvmArgs(jvmArguments)
|
||||
|
||||
if(developmentEnvironmentUserName) {
|
||||
args("--username", developmentEnvironmentUserName)
|
||||
}
|
||||
}
|
||||
|
||||
serverIntellijRun {
|
||||
args(arguments)
|
||||
jvmArgs(jvmArguments)
|
||||
}
|
||||
}
|
||||
|
||||
if(file('addon.gradle').exists()) {
|
||||
apply from: 'addon.gradle'
|
||||
}
|
||||
|
||||
apply from: 'repositories.gradle'
|
||||
|
||||
configurations {
|
||||
implementation.extendsFrom(shadowImplementation) // TODO: remove after all uses are refactored
|
||||
implementation.extendsFrom(shadowCompile)
|
||||
implementation.extendsFrom(shadeCompile)
|
||||
}
|
||||
|
||||
repositories {
|
||||
flatDir {
|
||||
dirs 'libs'
|
||||
maven {
|
||||
name 'Overmind forge repo mirror'
|
||||
url 'https://gregtech.overminddl1.com/'
|
||||
}
|
||||
if(usesMixins.toBoolean() || forceEnableMixins) {
|
||||
maven {
|
||||
name 'sponge'
|
||||
url 'https://repo.spongepowered.org/repository/maven-public'
|
||||
}
|
||||
maven {
|
||||
url 'https://jitpack.io'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
processResources {
|
||||
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
include 'mcmod.info'
|
||||
expand 'version': project.version,
|
||||
'mod_id': mod_id,
|
||||
'mod_name': mod_name,
|
||||
'mod_author': mod_author,
|
||||
'mod_description': mod_description,
|
||||
'mc_version': mc_version,
|
||||
'mod_version': mod_version,
|
||||
'mod_icon': mod_icon
|
||||
dependencies {
|
||||
if(usesMixins.toBoolean()) {
|
||||
annotationProcessor('org.ow2.asm:asm-debug-all:5.0.3')
|
||||
annotationProcessor('com.google.guava:guava:24.1.1-jre')
|
||||
annotationProcessor('com.google.code.gson:gson:2.8.6')
|
||||
annotationProcessor('org.spongepowered:mixin:0.8-SNAPSHOT')
|
||||
}
|
||||
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
exclude 'mcmod.info'
|
||||
if(usesMixins.toBoolean() || forceEnableMixins) {
|
||||
// using 0.8 to workaround a issue in 0.7 which fails mixin application
|
||||
compile('com.github.GTNewHorizons:SpongePoweredMixin:0.7.12-GTNH') {
|
||||
// Mixin includes a lot of dependencies that are too up-to-date
|
||||
exclude module: 'launchwrapper'
|
||||
exclude module: 'guava'
|
||||
exclude module: 'gson'
|
||||
exclude module: 'commons-io'
|
||||
exclude module: 'log4j-core'
|
||||
}
|
||||
compile('com.github.GTNewHorizons:SpongeMixins:1.5.0')
|
||||
}
|
||||
}
|
||||
|
||||
task devJar(type: Jar) {
|
||||
classifier = 'dev'
|
||||
from sourceSets.main.output
|
||||
apply from: 'dependencies.gradle'
|
||||
|
||||
def mixingConfigRefMap = 'mixins.' + modId + '.refmap.json'
|
||||
def refMap = "${tasks.compileJava.temporaryDir}" + File.separator + mixingConfigRefMap
|
||||
def mixinSrg = "${tasks.reobf.temporaryDir}" + File.separator + "mixins.srg"
|
||||
|
||||
task generateAssets {
|
||||
if (usesMixins.toBoolean()) {
|
||||
def mixinConfigFile = getFile("/src/main/resources/mixins." + modId + ".json");
|
||||
if (!mixinConfigFile.exists()) {
|
||||
mixinConfigFile.text = """{
|
||||
"required": true,
|
||||
"minVersion": "0.7.11",
|
||||
"package": "${modGroup}.${mixinsPackage}",
|
||||
"plugin": "${modGroup}.${mixinPlugin}",
|
||||
"refmap": "${mixingConfigRefMap}",
|
||||
"target": "@env(DEFAULT)",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"mixins": [],
|
||||
"client": [],
|
||||
"server": []
|
||||
}
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task sourcesJar(type: Jar) {
|
||||
classifier = 'sources'
|
||||
from sourceSets.main.allSource
|
||||
task relocateShadowJar(type: ConfigureShadowRelocation) {
|
||||
target = tasks.shadowJar
|
||||
prefix = modGroup + ".shadow"
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
project.configurations.shadeCompile.each { dep ->
|
||||
from(project.zipTree(dep)) {
|
||||
exclude 'META-INF', 'META-INF/**'
|
||||
}
|
||||
}
|
||||
|
||||
reobf {
|
||||
addExtraSrgFile project.mixinSrg
|
||||
manifest {
|
||||
attributes(getManifestAttributes())
|
||||
}
|
||||
|
||||
minimize() // This will only allow shading for actually used classes
|
||||
configurations = [
|
||||
project.configurations.shadowImplementation,
|
||||
project.configurations.shadowCompile
|
||||
]
|
||||
dependsOn(relocateShadowJar)
|
||||
}
|
||||
|
||||
jar {
|
||||
appendix project.minecraft.version
|
||||
project.configurations.shadeCompile.each { dep ->
|
||||
from(project.zipTree(dep)) {
|
||||
exclude 'META-INF', 'META-INF/**'
|
||||
}
|
||||
}
|
||||
|
||||
manifest {
|
||||
attributes(getManifestAttributes())
|
||||
}
|
||||
|
||||
if(usesShadowedDependencies.toBoolean()) {
|
||||
dependsOn(shadowJar)
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
|
||||
reobf {
|
||||
if(usesMixins.toBoolean()) {
|
||||
addExtraSrgFile mixinSrg
|
||||
}
|
||||
}
|
||||
|
||||
afterEvaluate {
|
||||
if(usesMixins.toBoolean()) {
|
||||
tasks.compileJava {
|
||||
options.compilerArgs += [
|
||||
"-AreobfSrgFile=${tasks.reobf.srg}",
|
||||
"-AoutSrgFile=${mixinSrg}",
|
||||
"-AoutRefMapFile=${refMap}",
|
||||
// Elan: from what I understand they are just some linter configs so you get some warning on how to properly code
|
||||
"-XDenableSunApiLintControl",
|
||||
"-XDignore.symbol.file"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
runClient {
|
||||
if(developmentEnvironmentUserName) {
|
||||
arguments += [
|
||||
"--username",
|
||||
developmentEnvironmentUserName
|
||||
]
|
||||
}
|
||||
|
||||
args(arguments)
|
||||
jvmArgs(jvmArguments)
|
||||
}
|
||||
|
||||
runServer {
|
||||
args(arguments)
|
||||
jvmArgs(jvmArguments)
|
||||
}
|
||||
|
||||
tasks.withType(JavaExec).configureEach {
|
||||
javaLauncher.set(
|
||||
javaToolchains.launcherFor {
|
||||
languageVersion = projectJavaVersion
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
processResources {
|
||||
// this will ensure that this task is redone when the versions change.
|
||||
inputs.property "version", project.version
|
||||
inputs.property "mcversion", project.minecraft.version
|
||||
exclude("spotless.gradle")
|
||||
|
||||
// replace stuff in mcmod.info, nothing else
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
include 'mcmod.info'
|
||||
|
||||
// replace modVersion and minecraftVersion
|
||||
expand "minecraftVersion": project.minecraft.version,
|
||||
"modVersion": modVersion,
|
||||
"modId": modId,
|
||||
"modName": modName
|
||||
}
|
||||
|
||||
if(usesMixins.toBoolean()) {
|
||||
from refMap
|
||||
}
|
||||
|
||||
// copy everything else that's not the mcmod.info
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
exclude 'mcmod.info'
|
||||
exclude 'spotless.gradle'
|
||||
}
|
||||
}
|
||||
|
||||
def getManifestAttributes() {
|
||||
def manifestAttributes = [:]
|
||||
if(!containsMixinsAndOrCoreModOnly.toBoolean() && (usesMixins.toBoolean() || coreModClass)) {
|
||||
manifestAttributes += ["FMLCorePluginContainsFMLMod": true]
|
||||
}
|
||||
|
||||
if(accessTransformersFile) {
|
||||
manifestAttributes += ["FMLAT" : accessTransformersFile.toString()]
|
||||
}
|
||||
|
||||
if(coreModClass) {
|
||||
manifestAttributes += ["FMLCorePlugin": modGroup + "." + coreModClass]
|
||||
}
|
||||
|
||||
if(usesMixins.toBoolean()) {
|
||||
manifestAttributes += [
|
||||
"TweakClass" : "org.spongepowered.asm.launch.MixinTweaker",
|
||||
"MixinConfigs" : "mixins." + modId + ".json",
|
||||
"ForceLoadAsMod" : !containsMixinsAndOrCoreModOnly.toBoolean()
|
||||
]
|
||||
}
|
||||
return manifestAttributes
|
||||
}
|
||||
|
||||
task sourcesJar(type: Jar) {
|
||||
from (sourceSets.main.allSource)
|
||||
from (file("$projectDir/LICENSE"))
|
||||
getArchiveClassifier().set('sources')
|
||||
}
|
||||
|
||||
task shadowDevJar(type: ShadowJar) {
|
||||
project.configurations.shadeCompile.each { dep ->
|
||||
from(project.zipTree(dep)) {
|
||||
exclude 'META-INF', 'META-INF/**'
|
||||
}
|
||||
}
|
||||
|
||||
from sourceSets.main.output
|
||||
getArchiveClassifier().set("dev")
|
||||
|
||||
manifest {
|
||||
attributes(getManifestAttributes())
|
||||
}
|
||||
|
||||
minimize() // This will only allow shading for actually used classes
|
||||
configurations = [
|
||||
project.configurations.shadowImplementation,
|
||||
project.configurations.shadowCompile
|
||||
]
|
||||
}
|
||||
|
||||
task relocateShadowDevJar(type: ConfigureShadowRelocation) {
|
||||
target = tasks.shadowDevJar
|
||||
prefix = modGroup + ".shadow"
|
||||
}
|
||||
|
||||
task circularResolverJar(type: Jar) {
|
||||
dependsOn(relocateShadowDevJar)
|
||||
dependsOn(shadowDevJar)
|
||||
enabled = false
|
||||
}
|
||||
|
||||
task devJar(type: Jar) {
|
||||
project.configurations.shadeCompile.each { dep ->
|
||||
from(project.zipTree(dep)) {
|
||||
exclude 'META-INF', 'META-INF/**'
|
||||
}
|
||||
}
|
||||
|
||||
from sourceSets.main.output
|
||||
getArchiveClassifier().set("dev")
|
||||
|
||||
manifest {
|
||||
attributes(getManifestAttributes())
|
||||
}
|
||||
|
||||
if(usesShadowedDependencies.toBoolean()) {
|
||||
dependsOn(circularResolverJar)
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
|
||||
task apiJar(type: Jar) {
|
||||
from (sourceSets.main.allSource) {
|
||||
include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**'
|
||||
}
|
||||
|
||||
from (sourceSets.main.output) {
|
||||
include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**'
|
||||
}
|
||||
|
||||
from (sourceSets.main.resources.srcDirs) {
|
||||
include("LICENSE")
|
||||
}
|
||||
|
||||
getArchiveClassifier().set('api')
|
||||
}
|
||||
|
||||
artifacts {
|
||||
if(!noPublishedSources) {
|
||||
archives sourcesJar
|
||||
}
|
||||
archives devJar
|
||||
archives sourcesJar
|
||||
if(apiPackage) {
|
||||
archives apiJar
|
||||
}
|
||||
}
|
||||
|
||||
// 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 {
|
||||
publications {
|
||||
maven(MavenPublication) {
|
||||
from components.java
|
||||
if(usesShadowedDependencies.toBoolean()) {
|
||||
artifact source: shadowJar, classifier: ""
|
||||
}
|
||||
if(!noPublishedSources) {
|
||||
artifact source: sourcesJar, classifier: "sources"
|
||||
}
|
||||
artifact source: usesShadowedDependencies.toBoolean() ? shadowDevJar : devJar, classifier: "dev"
|
||||
if (apiPackage) {
|
||||
artifact source: apiJar, classifier: "api"
|
||||
}
|
||||
|
||||
groupId = System.getenv("ARTIFACT_GROUP_ID") ?: "com.github.GTNewHorizons"
|
||||
artifactId = System.getenv("ARTIFACT_ID") ?: project.name
|
||||
// Using the identified version, not project.version as it has the prepended 1.7.10
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
url = "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases"
|
||||
credentials {
|
||||
username = System.getenv("MAVEN_USER") ?: "NONE"
|
||||
password = System.getenv("MAVEN_PASSWORD") ?: "NONE"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Updating
|
||||
task updateBuildScript {
|
||||
doLast {
|
||||
if (performBuildScriptUpdate(projectDir.toString())) return
|
||||
|
||||
print("Build script already up-to-date!")
|
||||
}
|
||||
}
|
||||
|
||||
if (isNewBuildScriptVersionAvailable(projectDir.toString())) {
|
||||
if (autoUpdateBuildScript.toBoolean()) {
|
||||
performBuildScriptUpdate(projectDir.toString())
|
||||
} else {
|
||||
out.style(Style.SuccessHeader).println("Build script update available! Run 'gradle updateBuildScript'")
|
||||
}
|
||||
}
|
||||
|
||||
static URL availableBuildScriptUrl() {
|
||||
new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/main/build.gradle")
|
||||
}
|
||||
|
||||
boolean performBuildScriptUpdate(String projectDir) {
|
||||
if (isNewBuildScriptVersionAvailable(projectDir)) {
|
||||
def buildscriptFile = getFile("build.gradle")
|
||||
availableBuildScriptUrl().withInputStream { i -> buildscriptFile.withOutputStream { it << i } }
|
||||
out.style(Style.Success).print("Build script updated. Please REIMPORT the project or RESTART your IDE!")
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
boolean isNewBuildScriptVersionAvailable(String projectDir) {
|
||||
Map parameters = ["connectTimeout": 2000, "readTimeout": 2000]
|
||||
|
||||
String currentBuildScript = getFile("build.gradle").getText()
|
||||
String currentBuildScriptHash = getVersionHash(currentBuildScript)
|
||||
String availableBuildScript = availableBuildScriptUrl().newInputStream(parameters).getText()
|
||||
String availableBuildScriptHash = getVersionHash(availableBuildScript)
|
||||
|
||||
boolean isUpToDate = currentBuildScriptHash.empty || availableBuildScriptHash.empty || currentBuildScriptHash == availableBuildScriptHash
|
||||
return !isUpToDate
|
||||
}
|
||||
|
||||
static String getVersionHash(String buildScriptContent) {
|
||||
String versionLine = buildScriptContent.find("^//version: [a-z0-9]*")
|
||||
if(versionLine != null) {
|
||||
return versionLine.split(": ").last()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
configure(updateBuildScript) {
|
||||
group = 'forgegradle'
|
||||
description = 'Updates the build script to the latest version'
|
||||
}
|
||||
|
||||
// Parameter Deobfuscation
|
||||
|
||||
task deobfParams {
|
||||
doLast {
|
||||
|
||||
String mcpDir = "$project.gradle.gradleUserHomeDir/caches/minecraft/de/oceanlabs/mcp/mcp_$channel/$mappingsVersion"
|
||||
String mcpZIP = "$mcpDir/mcp_$channel-$mappingsVersion-${minecraftVersion}.zip"
|
||||
String paramsCSV = "$mcpDir/params.csv"
|
||||
|
||||
download.run {
|
||||
src "https://maven.minecraftforge.net/de/oceanlabs/mcp/mcp_$channel/$mappingsVersion-$minecraftVersion/mcp_$channel-$mappingsVersion-${minecraftVersion}.zip"
|
||||
dest mcpZIP
|
||||
overwrite false
|
||||
}
|
||||
|
||||
if(!file(paramsCSV).exists()) {
|
||||
println("Extracting MCP archive ...")
|
||||
unzip(mcpZIP, mcpDir)
|
||||
}
|
||||
|
||||
println("Parsing params.csv ...")
|
||||
Map<String, String> params = new HashMap<>()
|
||||
Files.lines(Paths.get(paramsCSV)).forEach{line ->
|
||||
String[] cells = line.split(",")
|
||||
if(cells.length > 2 && cells[0].matches("p_i?\\d+_\\d+_")) {
|
||||
params.put(cells[0], cells[1])
|
||||
}
|
||||
}
|
||||
|
||||
out.style(Style.Success).println("Modified ${replaceParams(file("$projectDir/src/main/java"), params)} files!")
|
||||
out.style(Style.Failure).println("Don't forget to verify that the code still works as before!\n It could be broken due to duplicate variables existing now\n or parameters taking priority over other variables.")
|
||||
}
|
||||
}
|
||||
|
||||
static int replaceParams(File file, Map<String, String> params) {
|
||||
int fileCount = 0
|
||||
|
||||
if(file.isDirectory()) {
|
||||
for(File f : file.listFiles()) {
|
||||
fileCount += replaceParams(f, params)
|
||||
}
|
||||
return fileCount
|
||||
}
|
||||
println("Visiting ${file.getName()} ...")
|
||||
try {
|
||||
String content = new String(Files.readAllBytes(file.toPath()))
|
||||
int hash = content.hashCode()
|
||||
params.forEach{key, value ->
|
||||
content = content.replaceAll(key, value)
|
||||
}
|
||||
if(hash != content.hashCode()) {
|
||||
Files.write(file.toPath(), content.getBytes("UTF-8"))
|
||||
return 1
|
||||
}
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Credit: bitsnaps (https://gist.github.com/bitsnaps/00947f2dce66f4bbdabc67d7e7b33681)
|
||||
static unzip(String zipFileName, String outputDir) {
|
||||
byte[] buffer = new byte[16384]
|
||||
ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFileName))
|
||||
ZipEntry zipEntry = zis.getNextEntry()
|
||||
while (zipEntry != null) {
|
||||
File newFile = new File(outputDir + File.separator, zipEntry.name)
|
||||
if (zipEntry.isDirectory()) {
|
||||
if (!newFile.isDirectory() && !newFile.mkdirs()) {
|
||||
throw new IOException("Failed to create directory $newFile")
|
||||
}
|
||||
} else {
|
||||
// fix for Windows-created archives
|
||||
File parent = newFile.parentFile
|
||||
if (!parent.isDirectory() && !parent.mkdirs()) {
|
||||
throw new IOException("Failed to create directory $parent")
|
||||
}
|
||||
// write file content
|
||||
FileOutputStream fos = new FileOutputStream(newFile)
|
||||
int len = 0
|
||||
while ((len = zis.read(buffer)) > 0) {
|
||||
fos.write(buffer, 0, len)
|
||||
}
|
||||
fos.close()
|
||||
}
|
||||
zipEntry = zis.getNextEntry()
|
||||
}
|
||||
zis.closeEntry()
|
||||
zis.close()
|
||||
}
|
||||
|
||||
configure(deobfParams) {
|
||||
group = 'forgegradle'
|
||||
description = 'Rename all obfuscated parameter names inherited from Minecraft classes'
|
||||
}
|
||||
|
||||
// Dependency 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.endsWith(".litemod")) {
|
||||
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/${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 rawFileName) {
|
||||
String bon2Version = "2.5.1"
|
||||
String fileName = URLDecoder.decode(rawFileName, "UTF-8")
|
||||
String cacheDir = "$project.gradle.gradleUserHomeDir/caches"
|
||||
String bon2Dir = "$cacheDir/forge_gradle/deobf"
|
||||
String bon2File = "$bon2Dir/BON2-${bon2Version}.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)
|
||||
}
|
||||
|
||||
String mappingsVer
|
||||
if(remoteMappings) {
|
||||
String id = "${forgeVersion.split("\\.")[3]}-$minecraftVersion"
|
||||
String mappingsZIP = "$cacheDir/forge_gradle/maven_downloader/de/oceanlabs/mcp/mcp_snapshot_nodoc/$id/mcp_snapshot_nodoc-${id}.zip"
|
||||
|
||||
zipMappings(mappingsZIP, remoteMappings, bon2Dir)
|
||||
|
||||
mappingsVer = "snapshot_$id"
|
||||
} else {
|
||||
mappingsVer = "${channel}_$mappingsVersion"
|
||||
}
|
||||
|
||||
download.run {
|
||||
src "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases/com/github/parker8283/BON2/$bon2Version-CUSTOM/BON2-$bon2Version-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', minecraftVersion, '--mappingsVer', mappingsVer, '--notch'
|
||||
workingDir bon2Dir
|
||||
standardOutput = new FileOutputStream("${deobfFile}.log")
|
||||
}
|
||||
|
||||
return files(deobfFile)
|
||||
}
|
||||
|
||||
def zipMappings(String zipPath, String url, String bon2Dir) {
|
||||
File zipFile = new File(zipPath)
|
||||
if(zipFile.exists()) {
|
||||
return
|
||||
}
|
||||
|
||||
String fieldsCache = "$bon2Dir/data/fields.csv"
|
||||
String methodsCache = "$bon2Dir/data/methods.csv"
|
||||
|
||||
download.run {
|
||||
src "${url}fields.csv"
|
||||
dest fieldsCache
|
||||
quiet true
|
||||
}
|
||||
download.run {
|
||||
src "${url}methods.csv"
|
||||
dest methodsCache
|
||||
quiet true
|
||||
}
|
||||
|
||||
zipFile.getParentFile().mkdirs()
|
||||
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile))
|
||||
|
||||
zos.putNextEntry(new ZipEntry("fields.csv"))
|
||||
Files.copy(Paths.get(fieldsCache), zos)
|
||||
zos.closeEntry()
|
||||
|
||||
zos.putNextEntry(new ZipEntry("methods.csv"))
|
||||
Files.copy(Paths.get(methodsCache), zos)
|
||||
zos.closeEntry()
|
||||
|
||||
zos.close()
|
||||
}
|
||||
|
||||
// Helper methods
|
||||
|
||||
def checkPropertyExists(String propertyName) {
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
||||
def getFile(String relativePath) {
|
||||
return new File(projectDir, relativePath)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
// Add your dependencies here
|
||||
|
||||
dependencies {
|
||||
|
||||
}
|
||||
+77
-17
@@ -1,19 +1,79 @@
|
||||
# Gradle Specifications
|
||||
org.gradle.jvmargs=-Xmx2G -Xms2G
|
||||
org.gradle.daemon=false
|
||||
modName = BetterCrashes
|
||||
|
||||
# General Specifications
|
||||
mc_version=1.7.10
|
||||
mod_version=1.1.2
|
||||
forge_version=10.13.4.1614
|
||||
mod_group=vfyjxf.bettercrashes
|
||||
mod_id=bettercrashes
|
||||
mod_name=BetterCrashes
|
||||
mod_archives_name=BetterCrashes
|
||||
mod_author=vfyjxf
|
||||
mod_icon=TEM_logo.png
|
||||
mod_description=Some generic mod description
|
||||
mod_credits=Me, for making this amazing mod.
|
||||
# This is a case-sensitive string to identify your mod. Convention is to use lower case.
|
||||
modId = bettercrashes
|
||||
|
||||
# Grimoire Shenanigans
|
||||
mixinRefmapName=mixins.bettercrashes.refmap.json
|
||||
modGroup = vfyjxf.bettercrashes
|
||||
|
||||
# WHY is there no version field?
|
||||
# The build script relies on git to provide a version via tags. It is super easy and will enable you to always know the
|
||||
# code base or your binary. Check out this tutorial: https://blog.mattclemente.com/2017/10/13/versioning-with-git-tags/
|
||||
|
||||
# Will update your build.gradle automatically whenever an update is available
|
||||
autoUpdateBuildScript = false
|
||||
|
||||
minecraftVersion = 1.7.10
|
||||
forgeVersion = 10.13.4.1614
|
||||
|
||||
# Specify a MCP channel and mappings version for dependency deobfuscation and the deobfParams task.
|
||||
channel = stable
|
||||
mappingsVersion = 12
|
||||
|
||||
# Define other MCP mappings for dependency deobfuscation
|
||||
remoteMappings = https://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/
|
||||
|
||||
# Select a username for testing your mod with breakpoints. You may leave this empty for a random username each time you
|
||||
# restart Minecraft in development. Choose this dependent on your mod:
|
||||
# Do you need consistent player progressing (for example Thaumcraft)? -> Select a name
|
||||
# Do you need to test how your custom blocks interacts with a player that is not the owner? -> leave name empty
|
||||
developmentEnvironmentUserName = Developer
|
||||
|
||||
# Define a source file of your project with:
|
||||
# public static final String VERSION = "GRADLETOKEN_VERSION";
|
||||
# The string's content will be replaced with your mod's version when compiled. You should use this to specify your mod's
|
||||
# version in @Mod([...], version = VERSION, [...])
|
||||
# Leave these properties empty to skip individual token replacements
|
||||
replaceGradleTokenInFile = Tags.java
|
||||
gradleTokenModId = GRADLETOKEN_MODID
|
||||
gradleTokenModName = GRADLETOKEN_MODNAME
|
||||
gradleTokenVersion = GRADLETOKEN_VERSION
|
||||
gradleTokenGroupName = GRADLETOKEN_GROUPNAME
|
||||
|
||||
# In case your mod provides an API for other mods to implement you may declare its package here. Otherwise, you can
|
||||
# leave this property empty.
|
||||
# Example value: apiPackage = api + modGroup = com.myname.mymodid -> com.myname.mymodid.api
|
||||
apiPackage =
|
||||
|
||||
# Specify the configuration file for Forge's access transformers here. It must be placed into /src/main/resources/META-INF/
|
||||
# Example value: mymodid_at.cfg
|
||||
accessTransformersFile =
|
||||
|
||||
# Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled!
|
||||
usesMixins = true
|
||||
# Adds some debug arguments like verbose output and export
|
||||
usesMixinDebug = false
|
||||
# Specify the location of your implementation of IMixinConfigPlugin. Leave it empty otherwise.
|
||||
mixinPlugin = mixinplugin.MixinPlugin
|
||||
# Specify the package that contains all of your Mixins. You may only place Mixins in this package or the build will fail!
|
||||
mixinsPackage = mixins
|
||||
# Specify the core mod entry class if you use a core mod. This class must implement IFMLLoadingPlugin!
|
||||
# This parameter is for legacy compatibility only
|
||||
# Example value: coreModClass = asm.FMLPlugin + modGroup = com.myname.mymodid -> com.myname.mymodid.asm.FMLPlugin
|
||||
coreModClass =
|
||||
# If your project is only a consolidation of mixins or a core mod and does NOT contain a 'normal' mod ( = some class
|
||||
# that is annotated with @Mod) you want this to be true. When in doubt: leave it on false!
|
||||
containsMixinsAndOrCoreModOnly = false
|
||||
|
||||
# Enables Mixins even if this mod doesn't use them, useful if one of the dependencies uses mixins.
|
||||
forceEnableMixins = false
|
||||
|
||||
# If enabled, you may use 'shadowCompile' for dependencies. They will be integrated in your jar. It is your
|
||||
# responsibility check the licence and request permission for distribution, if required.
|
||||
usesShadowedDependencies = false
|
||||
|
||||
# Optional parameter to customize the produced artifacts. Use this to preserver artifact naming when migrating older
|
||||
# projects. New projects should not use this parameter.
|
||||
#customArchiveBaseName =
|
||||
|
||||
# Optional parameter to prevent the source code from being published
|
||||
# noPublishedSources =
|
||||
Vendored
BIN
Binary file not shown.
+1
-2
@@ -1,6 +1,5 @@
|
||||
#Wed Jul 02 15:54:47 CDT 2014
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.9.1-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
|
||||
@@ -0,0 +1,5 @@
|
||||
// Add any additional repositories for your dependencies here
|
||||
|
||||
repositories {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
plugins {
|
||||
id 'com.diffplug.blowdryerSetup' version '1.6.0'
|
||||
}
|
||||
|
||||
apply plugin: 'com.diffplug.blowdryerSetup'
|
||||
|
||||
blowdryerSetup {
|
||||
github('GTNewHorizons/ExampleMod1.7.10', 'tag', '0.1.4')
|
||||
//devLocal '.' // Use this when testing config updates locally
|
||||
}
|
||||
@@ -1,17 +1,18 @@
|
||||
package vfyjxf.bettercrashes;
|
||||
|
||||
|
||||
import cpw.mods.fml.common.Mod;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@Mod(modid = BetterCrashes.MODID, version = BetterCrashes.VERSION, name = BetterCrashes.NAME,dependencies = BetterCrashes.DEPENDENCIES)
|
||||
@Mod(
|
||||
modid = BetterCrashes.MODID,
|
||||
version = BetterCrashes.VERSION,
|
||||
name = BetterCrashes.NAME,
|
||||
dependencies = BetterCrashes.DEPENDENCIES)
|
||||
public class BetterCrashes {
|
||||
public static final String MODID = "bettercrashes";
|
||||
public static final String NAME = "BetterCrashes";
|
||||
public static final String VERSION = "@VERSION@";
|
||||
public static final String DEPENDENCIES = "required-after:grimoire";
|
||||
public static final String DEPENDENCIES = "";
|
||||
public static final Logger logger = LogManager.getLogger("BetterCrashes");
|
||||
|
||||
|
||||
}
|
||||
@@ -1,19 +1,21 @@
|
||||
package vfyjxf.bettercrashes;
|
||||
|
||||
import net.minecraftforge.common.config.Configuration;
|
||||
|
||||
import java.io.File;
|
||||
import net.minecraftforge.common.config.Configuration;
|
||||
|
||||
public class BetterCrashesConfig {
|
||||
|
||||
public static boolean enableUploadCrash = false;
|
||||
public static boolean enableUploadCrash = false;
|
||||
|
||||
public static void loadConfig(File configFile){
|
||||
public static void loadConfig(File configFile) {
|
||||
Configuration config = new Configuration(configFile);
|
||||
config.load();
|
||||
enableUploadCrash = config.get("upload","enableUploadCrash",false,
|
||||
"if true,we will use \"https://paste.ubuntu.com\" to upload crash report.").getBoolean();
|
||||
enableUploadCrash = config.get(
|
||||
"upload",
|
||||
"enableUploadCrash",
|
||||
false,
|
||||
"if true,we will use \"https://paste.ubuntu.com\" to upload crash report.")
|
||||
.getBoolean();
|
||||
config.save();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package vfyjxf.bettercrashes;
|
||||
|
||||
import io.github.crucible.grimoire.common.api.grimmix.Grimmix;
|
||||
import io.github.crucible.grimoire.common.api.grimmix.GrimmixController;
|
||||
import io.github.crucible.grimoire.common.api.grimmix.lifecycle.IConfigBuildingEvent;
|
||||
|
||||
@Grimmix(id = "bettercrashesgrimmix", name = "Better Crashes Grimmix")
|
||||
public class BetterCrashesGrimmix extends GrimmixController {
|
||||
|
||||
@Override
|
||||
public void buildMixinConfigs(IConfigBuildingEvent event) {
|
||||
event.createBuilder("bettercrashes/mixins.bettercrashes.json")
|
||||
.mixinPackage("vfyjxf.bettercrashes.mixins")
|
||||
.clientMixins("client.MixinMinecraft")
|
||||
.commonMixins("MixinCrashReport")
|
||||
.refmap("@MIXIN_REFMAP@")
|
||||
.verbose(true)
|
||||
.required(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package vfyjxf.bettercrashes.mixinplugin;
|
||||
|
||||
import static vfyjxf.bettercrashes.mixinplugin.TargetedMod.VANILLA;
|
||||
|
||||
import cpw.mods.fml.relauncher.FMLLaunchHandler;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public enum Mixin {
|
||||
|
||||
//
|
||||
// IMPORTANT: Do not make any references to any mod from this file. This file is loaded quite early on and if
|
||||
// you refer to other mods you load them as well. The consequence is: You can't inject any previously loaded
|
||||
// classes!
|
||||
// Exception: Tags.java, as long as it is used for Strings only!
|
||||
//
|
||||
|
||||
MinecraftMixin("minecraft.MinecraftMixin", Side.BOTH, VANILLA),
|
||||
CrashReportMixin("minecraft.CrashReportMixin", Side.BOTH, VANILLA);
|
||||
|
||||
public final String mixinClass;
|
||||
public final List<TargetedMod> targetedMods;
|
||||
private final Side side;
|
||||
|
||||
Mixin(String mixinClass, Side side, TargetedMod... targetedMods) {
|
||||
this.mixinClass = mixinClass;
|
||||
this.targetedMods = Arrays.asList(targetedMods);
|
||||
this.side = side;
|
||||
}
|
||||
|
||||
Mixin(String mixinClass, TargetedMod... targetedMods) {
|
||||
this.mixinClass = mixinClass;
|
||||
this.targetedMods = Arrays.asList(targetedMods);
|
||||
this.side = Side.BOTH;
|
||||
}
|
||||
|
||||
public boolean shouldLoad(List<TargetedMod> loadedMods) {
|
||||
return (side == Side.BOTH
|
||||
|| side == Side.SERVER && FMLLaunchHandler.side().isServer()
|
||||
|| side == Side.CLIENT && FMLLaunchHandler.side().isClient())
|
||||
&& loadedMods.containsAll(targetedMods);
|
||||
}
|
||||
}
|
||||
|
||||
enum Side {
|
||||
BOTH,
|
||||
CLIENT,
|
||||
SERVER;
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package vfyjxf.bettercrashes.mixinplugin;
|
||||
|
||||
import static java.nio.file.Files.walk;
|
||||
import static vfyjxf.bettercrashes.mixinplugin.TargetedMod.VANILLA;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.spongepowered.asm.lib.tree.ClassNode;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
|
||||
import ru.timeconqueror.spongemixins.MinecraftURLClassPath;
|
||||
|
||||
public class MixinPlugin implements IMixinConfigPlugin {
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger("BetterCrashes mixins");
|
||||
private static final Path MODS_DIRECTORY_PATH = new File(Launch.minecraftHome, "mods/").toPath();
|
||||
|
||||
@Override
|
||||
public void onLoad(String mixinPackage) {}
|
||||
|
||||
@Override
|
||||
public String getRefMapperConfig() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) {}
|
||||
|
||||
// This method return a List<String> of mixins. Every mixins in this list will be loaded.
|
||||
@Override
|
||||
public List<String> getMixins() {
|
||||
final boolean isDevelopmentEnvironment = (boolean) Launch.blackboard.get("fml.deobfuscatedEnvironment");
|
||||
|
||||
List<TargetedMod> loadedMods = Arrays.stream(TargetedMod.values())
|
||||
.filter(mod -> mod == VANILLA || (mod.loadInDevelopment && isDevelopmentEnvironment) || loadJarOf(mod))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
for (TargetedMod mod : TargetedMod.values()) {
|
||||
if (loadedMods.contains(mod)) {
|
||||
LOG.info("Found " + mod.modName + "! Integrating now...");
|
||||
} else {
|
||||
LOG.info("Could not find " + mod.modName + "! Skipping integration....");
|
||||
}
|
||||
}
|
||||
|
||||
List<String> mixins = new ArrayList<>();
|
||||
for (Mixin mixin : Mixin.values()) {
|
||||
if (mixin.shouldLoad(loadedMods)) {
|
||||
mixins.add(mixin.mixinClass);
|
||||
LOG.debug("Loading mixin: " + mixin.mixinClass);
|
||||
}
|
||||
}
|
||||
return mixins;
|
||||
}
|
||||
|
||||
private boolean loadJarOf(final TargetedMod mod) {
|
||||
try {
|
||||
File jar = findJarOf(mod);
|
||||
if (jar == null) {
|
||||
LOG.info("Jar not found for " + mod);
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG.info("Attempting to add " + jar + " to the URL Class Path");
|
||||
if (!jar.exists()) {
|
||||
throw new FileNotFoundException(jar.toString());
|
||||
}
|
||||
MinecraftURLClassPath.addJar(jar);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static File findJarOf(final TargetedMod mod) {
|
||||
try {
|
||||
return walk(MODS_DIRECTORY_PATH)
|
||||
.filter(mod::isMatchingJar)
|
||||
.map(Path::toFile)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {}
|
||||
|
||||
@Override
|
||||
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package vfyjxf.bettercrashes.mixinplugin;
|
||||
|
||||
import com.google.common.io.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public enum TargetedMod {
|
||||
|
||||
//
|
||||
// IMPORTANT: Do not make any references to any mod from this file. This file is loaded quite early on and if
|
||||
// you refer to other mods you load them as well. The consequence is: You can't inject any previously loaded
|
||||
// classes!
|
||||
// Exception: Tags.java, as long as it is used for Strings only!
|
||||
//
|
||||
|
||||
// Replace with your injected mods here, but always keep VANILLA:
|
||||
VANILLA("Minecraft", "unused", true);
|
||||
|
||||
public final String modName;
|
||||
public final String jarNamePrefixLowercase;
|
||||
// Optional dependencies can be omitted in development. Especially skipping GT5U will drastically speed up your game
|
||||
// start!
|
||||
public final boolean loadInDevelopment;
|
||||
|
||||
TargetedMod(String modName, String jarNamePrefix, boolean loadInDevelopment) {
|
||||
this.modName = modName;
|
||||
this.jarNamePrefixLowercase = jarNamePrefix.toLowerCase();
|
||||
this.loadInDevelopment = loadInDevelopment;
|
||||
}
|
||||
|
||||
public boolean isMatchingJar(Path path) {
|
||||
final String pathString = path.toString();
|
||||
final String nameLowerCase = Files.getNameWithoutExtension(pathString).toLowerCase();
|
||||
final String fileExtension = Files.getFileExtension(pathString);
|
||||
|
||||
return nameLowerCase.startsWith(jarNamePrefixLowercase) && "jar".equals(fileExtension);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TargetedMod{" + "modName='"
|
||||
+ modName + '\'' + ", jarNamePrefixLowercase='"
|
||||
+ jarNamePrefixLowercase + '\'' + '}';
|
||||
}
|
||||
}
|
||||
+45
-21
@@ -4,9 +4,16 @@
|
||||
*The source file uses the MIT License.
|
||||
*/
|
||||
|
||||
package vfyjxf.bettercrashes.mixins;
|
||||
package vfyjxf.bettercrashes.mixins.minecraft;
|
||||
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import net.minecraft.crash.CrashReport;
|
||||
import net.minecraft.crash.CrashReportCategory;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -22,24 +29,31 @@ import vfyjxf.bettercrashes.utils.IPatchedCrashReport;
|
||||
import vfyjxf.bettercrashes.utils.ModIdentifier;
|
||||
import vfyjxf.bettercrashes.utils.StacktraceDeobfuscator;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@Mixin(value = CrashReport.class, priority = 500)
|
||||
public class CrashReportMixin implements IPatchedCrashReport {
|
||||
@Shadow
|
||||
@Final
|
||||
private CrashReportCategory theReportCategory;
|
||||
|
||||
@Mixin(value = CrashReport.class,priority = 500)
|
||||
public class MixinCrashReport implements IPatchedCrashReport {
|
||||
@Shadow @Final private CrashReportCategory theReportCategory;
|
||||
@Shadow @Final private Throwable cause;
|
||||
@Shadow @Final private List<CrashReportCategory> crashReportSections;
|
||||
@Shadow @Final private String description;
|
||||
@Shadow
|
||||
@Final
|
||||
private Throwable cause;
|
||||
|
||||
@Shadow private static String getWittyComment() { return null; }
|
||||
@Shadow
|
||||
@Final
|
||||
private List<CrashReportCategory> crashReportSections;
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
private String description;
|
||||
|
||||
@Shadow
|
||||
private static String getWittyComment() {
|
||||
return null;
|
||||
}
|
||||
|
||||
private Set<ModContainer> suspectedMods;
|
||||
|
||||
@Override
|
||||
public Set<ModContainer> getSuspectedMods() {
|
||||
return suspectedMods;
|
||||
@@ -82,13 +96,22 @@ public class MixinCrashReport implements IPatchedCrashReport {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
builder.append("---- Minecraft Crash Report ----\n")
|
||||
.append("// ").append(getVanillaFixComment())
|
||||
.append("// ")
|
||||
.append(getVanillaFixComment())
|
||||
.append("\n\n")
|
||||
.append("Time: ").append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z").format(new Date())).append("\n")
|
||||
.append("Description: ").append(description)
|
||||
.append("Time: ")
|
||||
.append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z").format(new Date()))
|
||||
.append("\n")
|
||||
.append("Description: ")
|
||||
.append(description)
|
||||
.append("\n\n")
|
||||
.append(stacktraceToString(cause).replace("\t", " ")) // Vanilla's getCauseStackTraceOrString doesn't print causes and suppressed exceptions
|
||||
.append("\n\nA detailed walkthrough of the error, its code path and all known details is as follows:\n");
|
||||
.append(stacktraceToString(cause)
|
||||
.replace(
|
||||
"\t",
|
||||
" ")) // Vanilla's getCauseStackTraceOrString doesn't print causes and suppressed
|
||||
// exceptions
|
||||
.append(
|
||||
"\n\nA detailed walkthrough of the error, its code path and all known details is as follows:\n");
|
||||
|
||||
for (int i = 0; i < 87; i++) {
|
||||
builder.append("-");
|
||||
@@ -126,7 +149,8 @@ public class MixinCrashReport implements IPatchedCrashReport {
|
||||
String author = mod.getMetadata().authorList.get(0);
|
||||
return "I blame " + author + ".";
|
||||
}
|
||||
} catch (Throwable ignored) {}
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
|
||||
return getWittyComment();
|
||||
}
|
||||
+142
-64
@@ -4,10 +4,13 @@
|
||||
*The source file uses the MIT License.
|
||||
*/
|
||||
|
||||
package vfyjxf.bettercrashes.mixins.client;
|
||||
package vfyjxf.bettercrashes.mixins.minecraft;
|
||||
|
||||
import cpw.mods.fml.client.SplashProgress;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.audio.SoundHandler;
|
||||
import net.minecraft.client.gui.*;
|
||||
@@ -40,58 +43,114 @@ import vfyjxf.bettercrashes.utils.GuiCrashScreen;
|
||||
import vfyjxf.bettercrashes.utils.GuiInitErrorScreen;
|
||||
import vfyjxf.bettercrashes.utils.StateManager;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
|
||||
/**
|
||||
* @author Runemoro
|
||||
*/
|
||||
@Mixin(Minecraft.class)
|
||||
public abstract class MixinMinecraft{
|
||||
public abstract class MinecraftMixin {
|
||||
|
||||
@Shadow @Final private static Logger logger;
|
||||
@Shadow volatile boolean running;
|
||||
@Shadow private boolean hasCrashed;
|
||||
@Shadow private CrashReport crashReporter;
|
||||
@Shadow public static byte[] memoryReserve;
|
||||
@Shadow @Final private Queue field_152351_aB;// field_152351_aB --> scheduledTasks
|
||||
@Shadow public EntityRenderer entityRenderer;
|
||||
@Shadow private long field_83002_am;//field_83002_am-->debugCrashKeyPressTime
|
||||
@Shadow public GameSettings gameSettings;
|
||||
@Shadow public GuiIngame ingameGUI;
|
||||
@Shadow private List defaultResourcePacks;
|
||||
@Shadow private IReloadableResourceManager mcResourceManager;
|
||||
@Shadow public FontRenderer fontRenderer;
|
||||
@Shadow public TextureManager renderEngine;
|
||||
@Shadow private LanguageManager mcLanguageManager;
|
||||
@Shadow private SoundHandler mcSoundHandler;
|
||||
@Shadow @Final private IMetadataSerializer metadataSerializer_;
|
||||
@Shadow private Framebuffer framebufferMc;
|
||||
@Shadow public GuiScreen currentScreen;
|
||||
@Shadow private int leftClickCounter;
|
||||
@Shadow public int displayWidth;
|
||||
@Shadow public int displayHeight;
|
||||
@Shadow
|
||||
@Final
|
||||
private static Logger logger;
|
||||
|
||||
@Shadow protected abstract void startGame() throws LWJGLException;
|
||||
@Shadow public abstract void displayGuiScreen(GuiScreen guiScreenIn);
|
||||
@Shadow public abstract CrashReport addGraphicsAndWorldToCrashReport(CrashReport theCrash);
|
||||
@Shadow
|
||||
volatile boolean running;
|
||||
|
||||
@Shadow protected abstract void runGameLoop();
|
||||
@Shadow
|
||||
private boolean hasCrashed;
|
||||
|
||||
@Shadow public abstract NetHandlerPlayClient getNetHandler();
|
||||
@Shadow
|
||||
private CrashReport crashReporter;
|
||||
|
||||
@Shadow public abstract void loadWorld(WorldClient worldClientIn);
|
||||
@Shadow
|
||||
public static byte[] memoryReserve;
|
||||
|
||||
@Shadow public abstract void freeMemory();
|
||||
@Shadow
|
||||
@Final
|
||||
private Queue field_152351_aB; // field_152351_aB --> scheduledTasks
|
||||
|
||||
@Shadow public abstract void shutdownMinecraftApplet();
|
||||
@Shadow
|
||||
public EntityRenderer entityRenderer;
|
||||
|
||||
@Shadow public abstract void refreshResources();
|
||||
@Shadow
|
||||
private long field_83002_am; // field_83002_am-->debugCrashKeyPressTime
|
||||
|
||||
@Shadow protected abstract void checkGLError(String message);
|
||||
@Shadow
|
||||
public GameSettings gameSettings;
|
||||
|
||||
@Shadow public abstract void func_147120_f();// func_147120_f --> resetSize
|
||||
@Shadow
|
||||
public GuiIngame ingameGUI;
|
||||
|
||||
@Shadow
|
||||
private List defaultResourcePacks;
|
||||
|
||||
@Shadow
|
||||
private IReloadableResourceManager mcResourceManager;
|
||||
|
||||
@Shadow
|
||||
public FontRenderer fontRenderer;
|
||||
|
||||
@Shadow
|
||||
public TextureManager renderEngine;
|
||||
|
||||
@Shadow
|
||||
private LanguageManager mcLanguageManager;
|
||||
|
||||
@Shadow
|
||||
private SoundHandler mcSoundHandler;
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
private IMetadataSerializer metadataSerializer_;
|
||||
|
||||
@Shadow
|
||||
private Framebuffer framebufferMc;
|
||||
|
||||
@Shadow
|
||||
public GuiScreen currentScreen;
|
||||
|
||||
@Shadow
|
||||
private int leftClickCounter;
|
||||
|
||||
@Shadow
|
||||
public int displayWidth;
|
||||
|
||||
@Shadow
|
||||
public int displayHeight;
|
||||
|
||||
@SuppressWarnings("MixinAnnotationTarget")
|
||||
@Shadow
|
||||
protected abstract void func_71384_a() throws LWJGLException; // func_71384_a --> startGame
|
||||
|
||||
@Shadow
|
||||
public abstract void displayGuiScreen(GuiScreen guiScreenIn);
|
||||
|
||||
@Shadow
|
||||
public abstract CrashReport addGraphicsAndWorldToCrashReport(CrashReport theCrash);
|
||||
|
||||
@Shadow
|
||||
protected abstract void runGameLoop();
|
||||
|
||||
@Shadow
|
||||
public abstract NetHandlerPlayClient getNetHandler();
|
||||
|
||||
@Shadow
|
||||
public abstract void loadWorld(WorldClient worldClientIn);
|
||||
|
||||
@Shadow
|
||||
public abstract void freeMemory();
|
||||
|
||||
@Shadow
|
||||
public abstract void shutdownMinecraftApplet();
|
||||
|
||||
@Shadow
|
||||
public abstract void refreshResources();
|
||||
|
||||
@Shadow
|
||||
protected abstract void checkGLError(String message);
|
||||
|
||||
@Shadow
|
||||
public abstract void func_147120_f(); // func_147120_f --> resetSize
|
||||
|
||||
private int clientCrashCount = 0;
|
||||
private int serverCrashCount = 0;
|
||||
@@ -101,10 +160,10 @@ public abstract class MixinMinecraft{
|
||||
* @reason Overwrite Minecraft.run()
|
||||
*/
|
||||
@Overwrite
|
||||
public void run(){
|
||||
public void run() {
|
||||
running = true;
|
||||
try {
|
||||
startGame();
|
||||
func_71384_a();
|
||||
} catch (Throwable throwable) {
|
||||
CrashReport crashReport = CrashReport.makeCrashReport(throwable, "Initializing game");
|
||||
crashReport.makeCategory("Initialization");
|
||||
@@ -145,7 +204,6 @@ public abstract class MixinMinecraft{
|
||||
} finally {
|
||||
shutdownMinecraftApplet();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -159,7 +217,7 @@ public abstract class MixinMinecraft{
|
||||
// Reset hasCrashed, debugCrashKeyPressTime, and crashIntegratedServerNextTick
|
||||
hasCrashed = false;
|
||||
field_83002_am = -1;
|
||||
// crashIntegratedServerNextTick = false;
|
||||
// crashIntegratedServerNextTick = false;
|
||||
|
||||
// Vanilla does this when switching to main menu but not our custom crash screen
|
||||
// nor the out of memory screen (see https://bugs.mojang.com/browse/MC-128953)
|
||||
@@ -167,19 +225,25 @@ public abstract class MixinMinecraft{
|
||||
ingameGUI.getChatGUI().clearChatMessages();
|
||||
|
||||
// Display the crash screen
|
||||
// runGUILoop(new GuiCrashScreen(report));
|
||||
// runGUILoop(new GuiCrashScreen(report));
|
||||
displayGuiScreen(new GuiCrashScreen(report));
|
||||
} catch (Throwable t) {
|
||||
// The crash screen has crashed. Report it normally instead.
|
||||
logger.error("An uncaught exception occured while displaying the crash screen, making normal report instead", t);
|
||||
logger.error(
|
||||
"An uncaught exception occured while displaying the crash screen, making normal report instead", t);
|
||||
displayCrashReport(report);
|
||||
System.exit(report.getFile() != null ? -1 : -2);
|
||||
}
|
||||
}
|
||||
|
||||
private void addInfoToCrash(CrashReport crashReport){
|
||||
crashReport.getCategory().addCrashSectionCallable("Client Crashes Since Restart",() -> String.valueOf(clientCrashCount));
|
||||
crashReport.getCategory().addCrashSectionCallable("Integrated Server Crashes Since Restart", () -> String.valueOf(serverCrashCount));
|
||||
private void addInfoToCrash(CrashReport crashReport) {
|
||||
crashReport
|
||||
.getCategory()
|
||||
.addCrashSectionCallable("Client Crashes Since Restart", () -> String.valueOf(clientCrashCount));
|
||||
crashReport
|
||||
.getCategory()
|
||||
.addCrashSectionCallable(
|
||||
"Integrated Server Crashes Since Restart", () -> String.valueOf(serverCrashCount));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -194,12 +258,15 @@ public abstract class MixinMinecraft{
|
||||
originalMemoryReserveSize = memoryReserve.length;
|
||||
memoryReserve = new byte[0];
|
||||
}
|
||||
} catch (Throwable ignored) {}
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
|
||||
StateManager.resetStates();
|
||||
|
||||
if (getNetHandler() != null) {
|
||||
getNetHandler().getNetworkManager().closeChannel(new ChatComponentText("[BetterCrashes] Client crashed"));
|
||||
getNetHandler()
|
||||
.getNetworkManager()
|
||||
.closeChannel(new ChatComponentText("[BetterCrashes] Client crashed"));
|
||||
}
|
||||
loadWorld(null);
|
||||
if (entityRenderer.isShaderActive()) {
|
||||
@@ -210,14 +277,16 @@ public abstract class MixinMinecraft{
|
||||
if (originalMemoryReserveSize != -1) {
|
||||
try {
|
||||
memoryReserve = new byte[originalMemoryReserveSize];
|
||||
} catch (Throwable ignored) {}
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}
|
||||
System.gc();
|
||||
} catch (Throwable t) {
|
||||
logger.error("Failed to reset state after a crash", t);
|
||||
try {
|
||||
StateManager.resetStates();
|
||||
} catch (Throwable ignored) {}
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,7 +305,8 @@ public abstract class MixinMinecraft{
|
||||
mcResourceManager.registerReloadListener(mcLanguageManager);
|
||||
|
||||
refreshResources(); // TODO: Why is this necessary?
|
||||
fontRenderer = new FontRenderer(gameSettings, new ResourceLocation("textures/font/ascii.png"), renderEngine, false);
|
||||
fontRenderer = new FontRenderer(
|
||||
gameSettings, new ResourceLocation("textures/font/ascii.png"), renderEngine, false);
|
||||
mcResourceManager.registerReloadListener(fontRenderer);
|
||||
|
||||
mcSoundHandler = new SoundHandler(mcResourceManager, gameSettings);
|
||||
@@ -245,11 +315,14 @@ public abstract class MixinMinecraft{
|
||||
running = true;
|
||||
try {
|
||||
//noinspection deprecation
|
||||
SplashProgress.pause();// Disable the forge splash progress screen
|
||||
} catch (Throwable ignored) {}
|
||||
SplashProgress.pause(); // Disable the forge splash progress screen
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
runGUILoop(new GuiInitErrorScreen(report));
|
||||
} catch (Throwable t) {
|
||||
logger.error("An uncaught exception occured while displaying the init error screen, making normal report instead", t);
|
||||
logger.error(
|
||||
"An uncaught exception occured while displaying the init error screen, making normal report instead",
|
||||
t);
|
||||
displayCrashReport(report);
|
||||
System.exit(report.getFile() != null ? -1 : -2);
|
||||
}
|
||||
@@ -261,7 +334,10 @@ public abstract class MixinMinecraft{
|
||||
*/
|
||||
private void runGUILoop(GuiScreen screen) throws IOException {
|
||||
displayGuiScreen(screen);
|
||||
while (running && currentScreen != null && !(currentScreen instanceof GuiMainMenu) && !(Loader.isModLoaded("custommainmenu"))) {
|
||||
while (running
|
||||
&& currentScreen != null
|
||||
&& !(currentScreen instanceof GuiMainMenu)
|
||||
&& !(Loader.isModLoaded("custommainmenu"))) {
|
||||
if (Display.isCreated() && Display.isCloseRequested()) {
|
||||
System.exit(0);
|
||||
}
|
||||
@@ -277,11 +353,18 @@ public abstract class MixinMinecraft{
|
||||
GL11.glViewport(0, 0, displayWidth, displayHeight);
|
||||
|
||||
// EntityRenderer.setupOverlayRendering
|
||||
ScaledResolution scaledResolution = new ScaledResolution((Minecraft) (Object) this,displayWidth,displayHeight);
|
||||
ScaledResolution scaledResolution =
|
||||
new ScaledResolution((Minecraft) (Object) this, displayWidth, displayHeight);
|
||||
GL11.glClear(256);
|
||||
GL11.glMatrixMode(5889);
|
||||
GL11.glLoadIdentity();
|
||||
GL11.glOrtho(0.0D, scaledResolution.getScaledWidth_double(), scaledResolution.getScaledHeight_double(), 0, 1000, 3000);
|
||||
GL11.glOrtho(
|
||||
0.0D,
|
||||
scaledResolution.getScaledWidth_double(),
|
||||
scaledResolution.getScaledHeight_double(),
|
||||
0,
|
||||
1000,
|
||||
3000);
|
||||
GL11.glMatrixMode(5888);
|
||||
GL11.glLoadIdentity();
|
||||
GL11.glTranslatef(0, 0, -2000);
|
||||
@@ -307,7 +390,6 @@ public abstract class MixinMinecraft{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @author Runemoro
|
||||
* @reason
|
||||
@@ -317,8 +399,4 @@ public abstract class MixinMinecraft{
|
||||
public void displayCrashReport(CrashReport report) {
|
||||
CrashUtils.outputReport(report);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package vfyjxf.bettercrashes.utils;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.HttpURLConnection;
|
||||
@@ -9,7 +8,6 @@ import java.net.URLEncoder;
|
||||
|
||||
public class CrashReportUpload {
|
||||
|
||||
|
||||
public static String uploadToUbuntuPastebin(String url, String crashReport) throws IOException {
|
||||
URL pasteUrl = new URL(url);
|
||||
HttpURLConnection connection = (HttpURLConnection) pasteUrl.openConnection();
|
||||
@@ -32,5 +30,4 @@ public class CrashReportUpload {
|
||||
}
|
||||
return url + resultUrl;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,15 +6,14 @@
|
||||
|
||||
package vfyjxf.bettercrashes.utils;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.crash.CrashReport;
|
||||
import vfyjxf.bettercrashes.BetterCrashes;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.crash.CrashReport;
|
||||
import vfyjxf.bettercrashes.BetterCrashes;
|
||||
|
||||
/**
|
||||
* @author Runemoro
|
||||
@@ -33,7 +32,9 @@ public class CrashUtils {
|
||||
reportName += Minecraft.getMinecraft().func_152345_ab() ? "-client" : "-server";
|
||||
reportName += ".txt";
|
||||
|
||||
File reportsDir = isClient() ? new File(Minecraft.getMinecraft().mcDataDir, "crash-reports") : new File("crash-reports");
|
||||
File reportsDir = isClient()
|
||||
? new File(Minecraft.getMinecraft().mcDataDir, "crash-reports")
|
||||
: new File("crash-reports");
|
||||
File reportFile = new File(reportsDir, reportName);
|
||||
|
||||
report.saveToFile(reportFile);
|
||||
@@ -42,7 +43,10 @@ public class CrashUtils {
|
||||
BetterCrashes.logger.fatal("Failed saving report", e);
|
||||
}
|
||||
|
||||
BetterCrashes.logger.fatal("Minecraft ran into a problem! " + (report.getFile() != null ? "Report saved to: " + report.getFile() : "Crash report could not be saved.")
|
||||
BetterCrashes.logger.fatal("Minecraft ran into a problem! "
|
||||
+ (report.getFile() != null
|
||||
? "Report saved to: " + report.getFile()
|
||||
: "Crash report could not be saved.")
|
||||
+ "\n" + report.getCompleteReport());
|
||||
}
|
||||
|
||||
@@ -64,14 +68,13 @@ public class CrashUtils {
|
||||
*/
|
||||
public static void openCrashReport(CrashReport crashReport) throws IOException {
|
||||
|
||||
if(!Desktop.isDesktopSupported()){
|
||||
if (!Desktop.isDesktopSupported()) {
|
||||
BetterCrashes.logger.error("Desktop is not supported");
|
||||
return;
|
||||
}
|
||||
File report = crashReport.getFile();
|
||||
if(report.exists()){
|
||||
if (report.exists()) {
|
||||
Desktop.getDesktop().open(report);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,7 +14,6 @@ import net.minecraft.client.gui.GuiOptionButton;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.crash.CrashReport;
|
||||
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public class GuiCrashScreen extends GuiProblemScreen {
|
||||
public GuiCrashScreen(CrashReport report) {
|
||||
@@ -24,7 +23,8 @@ public class GuiCrashScreen extends GuiProblemScreen {
|
||||
@Override
|
||||
public void initGui() {
|
||||
super.initGui();
|
||||
GuiOptionButton mainMenuButton = new GuiOptionButton(0, width / 2 - 50 - 115, height / 4 + 120 + 12, 110, 20, I18n.format("bettercrashes.gui.toTitle"));
|
||||
GuiOptionButton mainMenuButton = new GuiOptionButton(
|
||||
0, width / 2 - 50 - 115, height / 4 + 120 + 12, 110, 20, I18n.format("bettercrashes.gui.toTitle"));
|
||||
buttonList.add(mainMenuButton);
|
||||
}
|
||||
|
||||
@@ -39,7 +39,8 @@ public class GuiCrashScreen extends GuiProblemScreen {
|
||||
@Override
|
||||
public void drawScreen(int mouseX, int mouseY, float partialTicks) { // TODO: localize number of lines
|
||||
drawDefaultBackground();
|
||||
drawCenteredString(fontRendererObj, I18n.format("bettercrashes.crashscreen.title"), width / 2, height / 4 - 40, 0xFFFFFF);
|
||||
drawCenteredString(
|
||||
fontRendererObj, I18n.format("bettercrashes.crashscreen.title"), width / 2, height / 4 - 40, 0xFFFFFF);
|
||||
|
||||
int textColor = 0xD0D0D0;
|
||||
int x = width / 2 - 155;
|
||||
@@ -52,7 +53,14 @@ public class GuiCrashScreen extends GuiProblemScreen {
|
||||
|
||||
drawString(fontRendererObj, I18n.format("bettercrashes.crashscreen.paragraph2.line1"), x, y += 11, textColor);
|
||||
|
||||
drawCenteredString(fontRendererObj, report.getFile() != null ? "\u00A7n" + report.getFile().getName() : I18n.format("vanillafix.crashscreen.reportSaveFailed"), width / 2, y += 11, 0x00FF00);
|
||||
drawCenteredString(
|
||||
fontRendererObj,
|
||||
report.getFile() != null
|
||||
? "\u00A7n" + report.getFile().getName()
|
||||
: I18n.format("vanillafix.crashscreen.reportSaveFailed"),
|
||||
width / 2,
|
||||
y += 11,
|
||||
0x00FF00);
|
||||
|
||||
drawString(fontRendererObj, I18n.format("bettercrashes.crashscreen.paragraph3.line1"), x, y += 12, textColor);
|
||||
drawString(fontRendererObj, I18n.format("bettercrashes.crashscreen.paragraph3.line2"), x, y += 9, textColor);
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*The source file uses the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
package vfyjxf.bettercrashes.utils;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
@@ -14,7 +13,7 @@ import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.crash.CrashReport;
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public class GuiInitErrorScreen extends GuiProblemScreen{
|
||||
public class GuiInitErrorScreen extends GuiProblemScreen {
|
||||
|
||||
public GuiInitErrorScreen(CrashReport report) {
|
||||
super(report);
|
||||
@@ -24,8 +23,15 @@ public class GuiInitErrorScreen extends GuiProblemScreen{
|
||||
public void initGui() {
|
||||
mc.setIngameNotInFocus();
|
||||
buttonList.clear();
|
||||
buttonList.add(new GuiButton(1,width / 2 - 155, height / 4 + 120 + 12, 150, 20, I18n.format("bettercrashes.gui.openCrashReport")));
|
||||
buttonList.add(new GuiButton(2, width / 2 - 155 + 160, height / 4 + 120 + 12, 150, 20, I18n.format("bettercrashes.gui.uploadReportAndCopyLink")));
|
||||
buttonList.add(new GuiButton(
|
||||
1, width / 2 - 155, height / 4 + 120 + 12, 150, 20, I18n.format("bettercrashes.gui.openCrashReport")));
|
||||
buttonList.add(new GuiButton(
|
||||
2,
|
||||
width / 2 - 155 + 160,
|
||||
height / 4 + 120 + 12,
|
||||
150,
|
||||
20,
|
||||
I18n.format("bettercrashes.gui.uploadReportAndCopyLink")));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -36,7 +42,12 @@ public class GuiInitErrorScreen extends GuiProblemScreen{
|
||||
@Override
|
||||
public void drawScreen(int mouseX, int mouseY, float partialTicks) { // TODO: localize number of lines
|
||||
drawDefaultBackground();
|
||||
drawCenteredString(fontRendererObj, I18n.format("bettercrashes.initerrorscreen.title"), width / 2, height / 4 - 40, 0xFFFFFF);
|
||||
drawCenteredString(
|
||||
fontRendererObj,
|
||||
I18n.format("bettercrashes.initerrorscreen.title"),
|
||||
width / 2,
|
||||
height / 4 - 40,
|
||||
0xFFFFFF);
|
||||
|
||||
int textColor = 0xD0D0D0;
|
||||
int x = width / 2 - 155;
|
||||
@@ -49,12 +60,23 @@ public class GuiInitErrorScreen extends GuiProblemScreen{
|
||||
|
||||
drawString(fontRendererObj, I18n.format("bettercrashes.crashscreen.paragraph2.line1"), x, y += 11, textColor);
|
||||
|
||||
drawCenteredString(fontRendererObj, report.getFile() != null ? "\u00A7n" + report.getFile().getName() : I18n.format("vanillafix.crashscreen.reportSaveFailed"), width / 2, y += 11, 0x00FF00);
|
||||
drawCenteredString(
|
||||
fontRendererObj,
|
||||
report.getFile() != null
|
||||
? "\u00A7n" + report.getFile().getName()
|
||||
: I18n.format("vanillafix.crashscreen.reportSaveFailed"),
|
||||
width / 2,
|
||||
y += 11,
|
||||
0x00FF00);
|
||||
|
||||
drawString(fontRendererObj, I18n.format("bettercrashes.initerrorscreen.paragraph3.line1"), x, y += 12, textColor);
|
||||
drawString(fontRendererObj, I18n.format("bettercrashes.initerrorscreen.paragraph3.line2"), x, y += 9, textColor);
|
||||
drawString(fontRendererObj, I18n.format("bettercrashes.initerrorscreen.paragraph3.line3"), x, y += 9, textColor);
|
||||
drawString(fontRendererObj, I18n.format("bettercrashes.initerrorscreen.paragraph3.line4"), x, y += 9, textColor);
|
||||
drawString(
|
||||
fontRendererObj, I18n.format("bettercrashes.initerrorscreen.paragraph3.line1"), x, y += 12, textColor);
|
||||
drawString(
|
||||
fontRendererObj, I18n.format("bettercrashes.initerrorscreen.paragraph3.line2"), x, y += 9, textColor);
|
||||
drawString(
|
||||
fontRendererObj, I18n.format("bettercrashes.initerrorscreen.paragraph3.line3"), x, y += 9, textColor);
|
||||
drawString(
|
||||
fontRendererObj, I18n.format("bettercrashes.initerrorscreen.paragraph3.line4"), x, y += 9, textColor);
|
||||
super.drawScreen(mouseX, mouseY, partialTicks);
|
||||
}
|
||||
}
|
||||
@@ -9,20 +9,18 @@ package vfyjxf.bettercrashes.utils;
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.crash.CrashReport;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public abstract class GuiProblemScreen extends GuiScreen{
|
||||
public abstract class GuiProblemScreen extends GuiScreen {
|
||||
|
||||
protected final CrashReport report;
|
||||
private String hasteLink = null;
|
||||
@@ -36,13 +34,20 @@ public abstract class GuiProblemScreen extends GuiScreen{
|
||||
public void initGui() {
|
||||
mc.setIngameNotInFocus();
|
||||
buttonList.clear();
|
||||
buttonList.add(new GuiButton(1, width / 2 - 50, height / 4 + 120 + 12, 110, 20, I18n.format("bettercrashes.gui.openCrashReport")));
|
||||
buttonList.add(new GuiButton(2, width / 2 - 50 + 115, height / 4 + 120 + 12, 110, 20, I18n.format("bettercrashes.gui.uploadReportAndCopyLink")));
|
||||
buttonList.add(new GuiButton(
|
||||
1, width / 2 - 50, height / 4 + 120 + 12, 110, 20, I18n.format("bettercrashes.gui.openCrashReport")));
|
||||
buttonList.add(new GuiButton(
|
||||
2,
|
||||
width / 2 - 50 + 115,
|
||||
height / 4 + 120 + 12,
|
||||
110,
|
||||
20,
|
||||
I18n.format("bettercrashes.gui.uploadReportAndCopyLink")));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void actionPerformed(GuiButton button) {
|
||||
if (button.id == 1){
|
||||
if (button.id == 1) {
|
||||
try {
|
||||
CrashUtils.openCrashReport(report);
|
||||
} catch (IOException e) {
|
||||
@@ -51,10 +56,11 @@ public abstract class GuiProblemScreen extends GuiScreen{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if(button.id == 2){
|
||||
if(hasteLink == null){
|
||||
if (button.id == 2) {
|
||||
if (hasteLink == null) {
|
||||
try {
|
||||
hasteLink = CrashReportUpload.uploadToUbuntuPastebin("https://paste.ubuntu.com",report.getCompleteReport());
|
||||
hasteLink = CrashReportUpload.uploadToUbuntuPastebin(
|
||||
"https://paste.ubuntu.com", report.getCompleteReport());
|
||||
} catch (IOException e) {
|
||||
button.displayString = I18n.format("bettercrashes.gui.failed");
|
||||
button.enabled = false;
|
||||
@@ -63,7 +69,6 @@ public abstract class GuiProblemScreen extends GuiScreen{
|
||||
}
|
||||
setClipboardString(hasteLink);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
package vfyjxf.bettercrashes.utils;
|
||||
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,6 +4,8 @@ import net.minecraft.crash.CrashReport;
|
||||
|
||||
public interface IPatchedMinecraft {
|
||||
boolean shouldCrashIntegratedServerNextTick();
|
||||
|
||||
void showWarningScreen(CrashReport report);
|
||||
|
||||
void makeErrorNotification(CrashReport report);
|
||||
}
|
||||
@@ -8,17 +8,16 @@ package vfyjxf.bettercrashes.utils;
|
||||
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
import net.minecraft.launchwrapper.LaunchClassLoader;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
import net.minecraft.launchwrapper.LaunchClassLoader;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
/**
|
||||
* @author Runemoro
|
||||
@@ -65,7 +64,8 @@ public final class ModIdentifier {
|
||||
|
||||
// Get the mod containing that class
|
||||
try {
|
||||
if (url.getProtocol().equals("jar")) url = new URL(url.getFile().substring(0, url.getFile().indexOf('!')));
|
||||
if (url.getProtocol().equals("jar"))
|
||||
url = new URL(url.getFile().substring(0, url.getFile().indexOf('!')));
|
||||
return modMap.get(new File(url.toURI()).getCanonicalFile());
|
||||
} catch (URISyntaxException | IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
@@ -86,7 +86,8 @@ public final class ModIdentifier {
|
||||
|
||||
try {
|
||||
modMap.remove(Loader.instance().getMinecraftModContainer().getSource()); // Ignore minecraft jar (minecraft)
|
||||
modMap.remove(Loader.instance().getIndexedModList().get("FML").getSource()); // Ignore forge jar (FML, forge)
|
||||
modMap.remove(
|
||||
Loader.instance().getIndexedModList().get("FML").getSource()); // Ignore forge jar (FML, forge)
|
||||
} catch (NullPointerException ignored) {
|
||||
// Workaround for https://github.com/MinecraftForge/MinecraftForge/issues/4919
|
||||
}
|
||||
|
||||
@@ -20,7 +20,8 @@ import java.util.zip.ZipInputStream;
|
||||
* @author Runemoro
|
||||
*/
|
||||
public final class StacktraceDeobfuscator {
|
||||
private static final boolean DEBUG_IN_DEV = false; // Makes this MCP -> SRG for testing in dev. Don't forget to set to false when done!
|
||||
private static final boolean DEBUG_IN_DEV =
|
||||
false; // Makes this MCP -> SRG for testing in dev. Don't forget to set to false when done!
|
||||
private static HashMap<String, String> srgMcpMethodMap = null;
|
||||
|
||||
/**
|
||||
@@ -34,7 +35,8 @@ public final class StacktraceDeobfuscator {
|
||||
if (!mappings.exists()) {
|
||||
HttpURLConnection connection = null;
|
||||
try {
|
||||
URL mappingsURL = new URL("http://export.mcpbot.bspk.rs/mcp_stable_nodoc/39-1.12/mcp_stable_nodoc-39-1.12.zip");
|
||||
URL mappingsURL =
|
||||
new URL("http://export.mcpbot.bspk.rs/mcp_stable_nodoc/39-1.12/mcp_stable_nodoc-39-1.12.zip");
|
||||
connection = (HttpURLConnection) mappingsURL.openConnection();
|
||||
connection.setDoInput(true);
|
||||
connection.connect();
|
||||
@@ -72,9 +74,11 @@ public final class StacktraceDeobfuscator {
|
||||
String mappingLine = scanner.nextLine();
|
||||
int commaIndex = mappingLine.indexOf(',');
|
||||
String srgName = mappingLine.substring(0, commaIndex);
|
||||
String mcpName = mappingLine.substring(commaIndex + 1, commaIndex + 1 + mappingLine.substring(commaIndex + 1).indexOf(','));
|
||||
String mcpName = mappingLine.substring(
|
||||
commaIndex + 1,
|
||||
commaIndex + 1 + mappingLine.substring(commaIndex + 1).indexOf(','));
|
||||
|
||||
//System.out.println(srgName + " <=> " + mcpName);
|
||||
// System.out.println(srgName + " <=> " + mcpName);
|
||||
if (!DEBUG_IN_DEV) {
|
||||
srgMcpMethodMap.put(srgName, mcpName);
|
||||
} else {
|
||||
@@ -103,7 +107,8 @@ public final class StacktraceDeobfuscator {
|
||||
public static StackTraceElement[] deobfuscateStacktrace(StackTraceElement[] stackTrace) {
|
||||
int index = 0;
|
||||
for (StackTraceElement el : stackTrace) {
|
||||
stackTrace[index++] = new StackTraceElement(el.getClassName(), deobfuscateMethodName(el.getMethodName()), el.getFileName(), el.getLineNumber());
|
||||
stackTrace[index++] = new StackTraceElement(
|
||||
el.getClassName(), deobfuscateMethodName(el.getMethodName()), el.getFileName(), el.getLineNumber());
|
||||
}
|
||||
return stackTrace;
|
||||
}
|
||||
@@ -114,7 +119,8 @@ public final class StacktraceDeobfuscator {
|
||||
}
|
||||
|
||||
String mcpName = srgMcpMethodMap.get(srgName);
|
||||
// log.debug(srgName + " <=> " + mcpName != null ? mcpName : "?"); // Can't do this, it would be a recursive call to log appender
|
||||
// log.debug(srgName + " <=> " + mcpName != null ? mcpName : "?"); // Can't do this, it would be a recursive
|
||||
// call to log appender
|
||||
return mcpName != null ? mcpName : srgName;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
[{
|
||||
"modid": "${mod_id}",
|
||||
"name": "${mod_name}",
|
||||
"description": "${mod_description}",
|
||||
"version": "${mod_version}",
|
||||
"mcversion": "${mc_version}",
|
||||
"url": "",
|
||||
"modid": "${modId}",
|
||||
"name": "${modName}",
|
||||
"description": "BetterCrashes makes Minecraft return you to the main menu when it crashes.",
|
||||
"version": "${modVersion}",
|
||||
"mcversion": "${minecraftVersion}",
|
||||
"url": "https://github.com/GTNewHorizons/BetterCrashes",
|
||||
"updateUrl": "",
|
||||
"authorList": ["${mod_author}"],
|
||||
"authorList": [
|
||||
"vfyjxf"
|
||||
],
|
||||
"credits": "",
|
||||
"logoFile": "${mod_icon}",
|
||||
"logoFile": "",
|
||||
"screenshots": [],
|
||||
"dependencies": []
|
||||
}]
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"required": true,
|
||||
"minVersion": "0.7.11",
|
||||
"package": "vfyjxf.bettercrashes.mixins",
|
||||
"plugin": "vfyjxf.bettercrashes.mixinplugin.MixinPlugin",
|
||||
"refmap": "mixins.bettercrashes.refmap.json",
|
||||
"target": "@env(DEFAULT)",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"mixins": [],
|
||||
"client": [],
|
||||
"server": []
|
||||
}
|
||||
Reference in new issue
Block a user