diff --git a/build.gradle b/build.gradle index e2e8960..b894d64 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1675173326 +//version: 1692122114 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. @@ -6,27 +6,28 @@ */ -import com.diffplug.blowdryer.Blowdryer -import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import com.gtnewhorizons.retrofuturagradle.ObfuscationAttribute import com.gtnewhorizons.retrofuturagradle.mcp.ReobfuscatedJar +import com.gtnewhorizons.retrofuturagradle.minecraft.RunMinecraftTask +import com.gtnewhorizons.retrofuturagradle.util.Distribution import com.matthewprenger.cursegradle.CurseArtifact import com.matthewprenger.cursegradle.CurseRelation import com.modrinth.minotaur.dependencies.ModDependency import com.modrinth.minotaur.dependencies.VersionDependency import org.gradle.internal.logging.text.StyledTextOutput.Style import org.gradle.internal.logging.text.StyledTextOutputFactory -import org.jetbrains.gradle.ext.* +import org.gradle.internal.xml.XmlTransformer +import org.jetbrains.gradle.ext.Application +import org.jetbrains.gradle.ext.Gradle +import javax.inject.Inject import java.nio.file.Files import java.nio.file.Paths import java.util.concurrent.TimeUnit -import java.util.zip.ZipEntry -import java.util.zip.ZipOutputStream buildscript { repositories { - mavenLocal() mavenCentral() maven { @@ -47,6 +48,8 @@ buildscript { name 'Scala CI dependencies' url 'https://repo1.maven.org/maven2/' } + + mavenLocal() } } plugins { @@ -58,22 +61,26 @@ plugins { id 'org.jetbrains.kotlin.jvm' version '1.8.0' apply false id 'org.jetbrains.kotlin.kapt' version '1.8.0' apply false id 'com.google.devtools.ksp' version '1.8.0-1.0.9' apply false - id 'org.ajoberstar.grgit' version '4.1.1' // 4.1.1 is the last jvm8 supporting version ,unused, available for addon.gradle - id 'com.github.johnrengelman.shadow' version '7.1.2' apply false - id 'com.palantir.git-version' version '0.13.0' apply false // 0.13.0 is the last jvm8 supporting version - id 'de.undercouch.download' version '5.3.0' + id 'org.ajoberstar.grgit' version '4.1.1' // 4.1.1 is the last jvm8 supporting version, unused, available for addon.gradle + id 'com.github.johnrengelman.shadow' version '8.1.1' apply false + id 'com.palantir.git-version' version '3.0.0' apply false + id 'de.undercouch.download' version '5.4.0' id 'com.github.gmazzo.buildconfig' version '3.1.0' apply false // Unused, available for addon.gradle - id 'com.diffplug.spotless' version '6.7.2' apply false + id 'com.diffplug.spotless' version '6.13.0' apply false // 6.13.0 is the last jvm8 supporting version id 'com.modrinth.minotaur' version '2.+' apply false id 'com.matthewprenger.cursegradle' version '1.4.0' apply false - id 'com.gtnewhorizons.retrofuturagradle' version '1.1.3' + id 'com.gtnewhorizons.retrofuturagradle' version '1.3.24' } + +print("You might want to check out './gradlew :faq' if your build fails.\n") + boolean settingsupdated = verifySettingsGradle() settingsupdated = verifyGitAttributes() || settingsupdated if (settingsupdated) throw new GradleException("Settings has been updated, please re-run task.") -if (project.file('.git/HEAD').isFile()) { +// In submodules, .git is a file pointing to the real git dir +if (project.file('.git/HEAD').isFile() || project.file('.git').isFile()) { apply plugin: 'com.palantir.git-version' } @@ -108,6 +115,8 @@ propertyDefaultIfUnset("usesMixinDebug", project.usesMixins) propertyDefaultIfUnset("forceEnableMixins", false) propertyDefaultIfUnset("channel", "stable") propertyDefaultIfUnset("mappingsVersion", "12") +propertyDefaultIfUnset("usesMavenPublishing", true) +propertyDefaultIfUnset("mavenPublishUrl", "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases") propertyDefaultIfUnset("modrinthProjectId", "") propertyDefaultIfUnset("modrinthRelations", "") propertyDefaultIfUnset("curseForgeProjectId", "") @@ -122,7 +131,10 @@ propertyDefaultIfUnset("gradleTokenGroupName", "") propertyDefaultIfUnset("enableModernJavaSyntax", false) // On by default for new projects only propertyDefaultIfUnset("enableGenericInjection", false) // On by default for new projects only -project.extensions.add(Blowdryer, "Blowdryer", Blowdryer) // Make blowdryer available in "apply from:" scripts +// this is meant to be set using the user wide property file. by default we do nothing. +propertyDefaultIfUnset("ideaOverrideBuildType", "") // Can be nothing, "gradle" or "idea" + +project.extensions.add(com.diffplug.blowdryer.Blowdryer, "Blowdryer", com.diffplug.blowdryer.Blowdryer) // Make blowdryer available in "apply from:" scripts if (!disableSpotless) { apply plugin: 'com.diffplug.spotless' apply from: Blowdryer.file('spotless.gradle') @@ -143,13 +155,21 @@ java { } else { languageVersion.set(projectJavaVersion) } - vendor.set(JvmVendorSpec.ADOPTIUM) + vendor.set(JvmVendorSpec.AZUL) } if (!noPublishedSources) { withSourcesJar() } } +tasks.withType(JavaCompile).configureEach { + options.encoding = "UTF-8" +} + +tasks.withType(ScalaCompile).configureEach { + options.encoding = "UTF-8" +} + pluginManager.withPlugin('org.jetbrains.kotlin.jvm') { // If Kotlin is enabled in the project kotlin { @@ -183,14 +203,34 @@ configurations { canBeConsumed = false canBeResolved = false } + + create("devOnlyNonPublishable") { + description = "Runtime and compiletime dependencies that are not published alongside the jar (compileOnly + runtimeOnlyNonPublishable)" + canBeConsumed = false + canBeResolved = false + } + compileOnly.extendsFrom(devOnlyNonPublishable) + runtimeOnlyNonPublishable.extendsFrom(devOnlyNonPublishable) } if (enableModernJavaSyntax.toBoolean()) { + repositories { + mavenCentral { + mavenContent { + includeGroup("me.eigenraven.java8unsupported") + } + } + } + dependencies { annotationProcessor 'com.github.bsideup.jabel:jabel-javac-plugin:1.0.0' + // workaround for https://github.com/bsideup/jabel/issues/174 + annotationProcessor 'net.java.dev.jna:jna-platform:5.13.0' compileOnly('com.github.bsideup.jabel:jabel-javac-plugin:1.0.0') { transitive = false // We only care about the 1 annotation class } + // Allow using jdk.unsupported classes like sun.misc.Unsafe in the compiled code, working around JDK-8206937. + patchedMinecraft('me.eigenraven.java8unsupported:java-8-unsupported-shim:1.0.0') } tasks.withType(JavaCompile).configureEach { @@ -202,7 +242,7 @@ if (enableModernJavaSyntax.toBoolean()) { javaCompiler.set(javaToolchains.compilerFor { languageVersion.set(JavaLanguageVersion.of(17)) - vendor.set(JvmVendorSpec.ADOPTIUM) + vendor.set(JvmVendorSpec.AZUL) }) } } @@ -234,12 +274,14 @@ if (apiPackage) { } 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) + for (atFile in accessTransformersFile.split(",")) { + String targetFile = "src/main/resources/META-INF/" + atFile.trim() + if (!getFile(targetFile).exists()) { + throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile) + } + tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(targetFile) + tasks.srgifyBinpatchedJar.accessTransformerFiles.from(targetFile) } - tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(targetFile) - tasks.srgifyBinpatchedJar.accessTransformerFiles.from(targetFile) } else { boolean atsFound = false for (File at : sourceSets.getByName("main").resources.files) { @@ -317,7 +359,27 @@ catch (Exception ignored) { String identifiedVersion String versionOverride = System.getenv("VERSION") ?: null try { - identifiedVersion = versionOverride == null ? gitVersion() : versionOverride + // Produce a version based on the tag, or for branches something like 0.2.2-configurable-maven-and-extras.38+43090270b6-dirty + if (versionOverride == null) { + def gitDetails = versionDetails() + def isDirty = gitVersion().endsWith(".dirty") // No public API for this, isCleanTag has a different meaning + String branchName = gitDetails.branchName ?: (System.getenv('GIT_BRANCH') ?: 'git') + if (branchName.startsWith('origin/')) { + branchName = branchName.minus('origin/') + } + branchName = branchName.replaceAll("[^a-zA-Z0-9-]+", "-") // sanitize branch names for semver + identifiedVersion = gitDetails.lastTag ?: '${gitDetails.gitHash}' + if (gitDetails.commitDistance > 0) { + identifiedVersion += "-${branchName}.${gitDetails.commitDistance}+${gitDetails.gitHash}" + if (isDirty) { + identifiedVersion += "-dirty" + } + } else if (isDirty) { + identifiedVersion += "-${branchName}+${gitDetails.gitHash}-dirty" + } + } else { + identifiedVersion = versionOverride + } } catch (Exception ignored) { out.style(Style.Failure).text( @@ -339,9 +401,13 @@ if (identifiedVersion == versionOverride) { group = "com.github.GTNewHorizons" if (project.hasProperty("customArchiveBaseName") && customArchiveBaseName) { - archivesBaseName = customArchiveBaseName + base { + archivesName = customArchiveBaseName + } } else { - archivesBaseName = modId + base { + archivesName = modId + } } @@ -367,12 +433,14 @@ minecraft { injectMissingGenerics.set(true) } + username = developmentEnvironmentUserName.toString() + + lwjgl3Version = "3.3.2" + // Enable assertions in the current mod extraRunJvmArguments.add("-ea:${modGroup}") if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { - extraTweakClasses.add("org.spongepowered.asm.launch.MixinTweaker") - if (usesMixinDebug.toBoolean()) { extraRunJvmArguments.addAll([ "-Dmixin.debug.countInjections=true", @@ -401,6 +469,16 @@ configurations.configureEach { } } } + def obfuscationAttr = it.attributes.getAttribute(ObfuscationAttribute.OBFUSCATION_ATTRIBUTE) + if (obfuscationAttr != null && obfuscationAttr.name == ObfuscationAttribute.SRG) { + resolutionStrategy.eachDependency { DependencyResolveDetails details -> + // Remap CoFH core cursemaven dev jar to the obfuscated version for runObfClient/Server + if (details.requested.group == 'curse.maven' && details.requested.name.endsWith('-69162') && details.requested.version == '2388751') { + details.useVersion '2388750' + details.because 'Pick obfuscated jar' + } + } + } } // Ensure tests have access to minecraft classes @@ -413,10 +491,19 @@ sourceSets { } } -if (file('addon.gradle').exists()) { +if (file('addon.gradle.kts').exists()) { + apply from: 'addon.gradle.kts' +} else if (file('addon.gradle').exists()) { apply from: 'addon.gradle' } +// File for local tweaks not commited to Git +if (file('addon.local.gradle.kts').exists()) { + apply from: 'addon.local.gradle.kts' +} else if (file('addon.local.gradle').exists()) { + apply from: 'addon.local.gradle' +} + // Allow unsafe repos but warn repositories.configureEach { repo -> if (repo instanceof org.gradle.api.artifacts.repositories.UrlArtifactRepository) { @@ -427,11 +514,19 @@ repositories.configureEach { repo -> } } -apply from: 'repositories.gradle' +if (file('repositories.gradle.kts').exists()) { + apply from: 'repositories.gradle.kts' +} else if (file('repositories.gradle').exists()) { + apply from: 'repositories.gradle' +} else { + logger.error("Neither repositories.gradle.kts nor repositories.gradle was found, make sure you extracted the full ExampleMod template.") + throw new RuntimeException("Missing repositories.gradle[.kts]") +} configurations { + runtimeClasspath.extendsFrom(runtimeOnlyNonPublishable) + testRuntimeClasspath.extendsFrom(runtimeOnlyNonPublishable) for (config in [compileClasspath, runtimeClasspath, testCompileClasspath, testRuntimeClasspath]) { - config.extendsFrom(runtimeOnlyNonPublishable) if (usesShadowedDependencies.toBoolean()) { config.extendsFrom(shadowImplementation) // TODO: remove Compile after all uses are refactored to Implementation @@ -467,31 +562,42 @@ repositories { maven { name 'Overmind forge repo mirror' url 'https://gregtech.overminddl1.com/' - mavenContent { - excludeGroup("net.minecraftforge") // missing the `universal` artefact - } } maven { name = "GTNH Maven" url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" allowInsecureProtocol = true } - if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { - if (usesMixinDebug.toBoolean()) { - maven { - name = "Fabric Maven" - url = "https://maven.fabricmc.net/" - } + maven { + name 'sonatype' + url 'https://oss.sonatype.org/content/repositories/snapshots/' + content { + includeGroup "org.lwjgl" } } if (includeWellKnownRepositories.toBoolean()) { - maven { - name "CurseMaven" - url "https://cursemaven.com" - content { + exclusiveContent { + forRepository { + maven { + name "CurseMaven" + url "https://cursemaven.com" + } + } + filter { includeGroup "curse.maven" } } + exclusiveContent { + forRepository { + maven { + name = "Modrinth" + url = "https://api.modrinth.com/maven" + } + } + filter { + includeGroup "maven.modrinth" + } + } maven { name = "ic2" url = "https://maven.ic2.player.to/" @@ -515,35 +621,78 @@ repositories { } } +def mixinProviderGroup = "io.github.legacymoddingmc" +def mixinProviderModule = "unimixins" +def mixinProviderVersion = "0.1.7.1" +def mixinProviderSpecNoClassifer = "${mixinProviderGroup}:${mixinProviderModule}:${mixinProviderVersion}" +def mixinProviderSpec = "${mixinProviderSpecNoClassifer}:dev" +ext.mixinProviderSpec = mixinProviderSpec + +def mixingConfigRefMap = 'mixins.' + modId + '.refmap.json' + 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('com.gtnewhorizon:gtnhmixins:2.1.10:processor') + annotationProcessor(mixinProviderSpec) if (usesMixinDebug.toBoolean()) { runtimeOnlyNonPublishable('org.jetbrains:intellij-fernflower:1.2.1.16') } } - if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { - implementation('com.gtnewhorizon:gtnhmixins:2.1.10') + if (usesMixins.toBoolean()) { + implementation(modUtils.enableMixins(mixinProviderSpec, mixingConfigRefMap)) + } else if (forceEnableMixins.toBoolean()) { + runtimeOnlyNonPublishable(mixinProviderSpec) } } pluginManager.withPlugin('org.jetbrains.kotlin.kapt') { if (usesMixins.toBoolean()) { dependencies { - kapt('com.gtnewhorizon:gtnhmixins:2.1.10:processor') + kapt(mixinProviderSpec) } } } -apply from: 'dependencies.gradle' +// Replace old mixin mods with unimixins +// https://docs.gradle.org/8.0.2/userguide/resolution_rules.html#sec:substitution_with_classifier +configurations.all { + resolutionStrategy.dependencySubstitution { + substitute module('com.gtnewhorizon:gtnhmixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") + substitute module('com.github.GTNewHorizons:Mixingasm') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") + substitute module('com.github.GTNewHorizons:SpongePoweredMixin') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") + substitute module('com.github.GTNewHorizons:SpongeMixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") + substitute module('io.github.legacymoddingmc:unimixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Our previous unimixins upload was missing the dev classifier") + } +} -def mixingConfigRefMap = 'mixins.' + modId + '.refmap.json' -def mixinTmpDir = buildDir.path + File.separator + 'tmp' + File.separator + 'mixins' -def refMap = "${mixinTmpDir}" + File.separator + mixingConfigRefMap -def mixinSrg = "${mixinTmpDir}" + File.separator + "mixins.srg" +dependencies { + constraints { + def minGtnhLibVersion = "0.0.13" + implementation("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") { + because("fixes duplicate mod errors in java 17 configurations using old gtnhlib") + } + runtimeOnly("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") { + because("fixes duplicate mod errors in java 17 configurations using old gtnhlib") + } + devOnlyNonPublishable("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") { + because("fixes duplicate mod errors in java 17 configurations using old gtnhlib") + } + runtimeOnlyNonPublishable("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") { + because("fixes duplicate mod errors in java 17 configurations using old gtnhlib") + } + } +} + +if (file('dependencies.gradle.kts').exists()) { + apply from: 'dependencies.gradle.kts' +} else if (file('dependencies.gradle').exists()) { + apply from: 'dependencies.gradle' +} else { + logger.error("Neither dependencies.gradle.kts nor dependencies.gradle was found, make sure you extracted the full ExampleMod template.") + throw new RuntimeException("Missing dependencies.gradle[.kts]") +} tasks.register('generateAssets') { group = "GTNH Buildscript" @@ -575,46 +724,17 @@ tasks.register('generateAssets') { } if (usesMixins.toBoolean()) { - tasks.named("reobfJar", ReobfuscatedJar).configure { - extraSrgFiles.from(mixinSrg) - } - tasks.named("processResources").configure { dependsOn("generateAssets") } tasks.named("compileJava", JavaCompile).configure { - doFirst { - new File(mixinTmpDir).mkdirs() - } options.compilerArgs += [ - "-AreobfSrgFile=${tasks.reobfJar.srg.get().asFile}", - "-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" ] } - - pluginManager.withPlugin('org.jetbrains.kotlin.kapt') { - kapt { - correctErrorTypes = true - javacOptions { - option("-AreobfSrgFile=${tasks.reobfJar.srg.get().asFile}") - option("-AoutSrgFile=$mixinSrg") - option("-AoutRefMapFile=$refMap") - } - } - tasks.configureEach { task -> - if (task.name == "kaptKotlin") { - task.doFirst { - new File(mixinTmpDir).mkdirs() - } - } - } - } - } tasks.named("processResources", ProcessResources).configure { @@ -632,10 +752,158 @@ tasks.named("processResources", ProcessResources).configure { } if (usesMixins.toBoolean()) { - from refMap + dependsOn("compileJava", "compileScala") } } +ext.java17Toolchain = (JavaToolchainSpec spec) -> { + spec.languageVersion.set(JavaLanguageVersion.of(17)) + spec.vendor.set(JvmVendorSpec.matching("jetbrains")) +} + +ext.java17DependenciesCfg = configurations.create("java17Dependencies") { + extendsFrom(configurations.getByName("runtimeClasspath")) // Ensure consistent transitive dependency resolution + canBeConsumed = false +} +ext.java17PatchDependenciesCfg = configurations.create("java17PatchDependencies") { + canBeConsumed = false +} + +dependencies { + def lwjgl3ifyVersion = '1.4.0' + def asmVersion = '9.4' + if (modId != 'lwjgl3ify') { + java17Dependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}") + } + if (modId != 'hodgepodge') { + java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.2.26') + } + + java17PatchDependencies('net.minecraft:launchwrapper:1.17.2') {transitive = false} + java17PatchDependencies("org.ow2.asm:asm:${asmVersion}") + java17PatchDependencies("org.ow2.asm:asm-commons:${asmVersion}") + java17PatchDependencies("org.ow2.asm:asm-tree:${asmVersion}") + java17PatchDependencies("org.ow2.asm:asm-analysis:${asmVersion}") + java17PatchDependencies("org.ow2.asm:asm-util:${asmVersion}") + java17PatchDependencies('org.ow2.asm:asm-deprecated:7.1') + java17PatchDependencies("org.apache.commons:commons-lang3:3.12.0") + java17PatchDependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}:forgePatches") {transitive = false} +} + +ext.java17JvmArgs = [ + // Java 9+ support + "--illegal-access=warn", + "-Djava.security.manager=allow", + "-Dfile.encoding=UTF-8", + "--add-opens", "java.base/jdk.internal.loader=ALL-UNNAMED", + "--add-opens", "java.base/java.net=ALL-UNNAMED", + "--add-opens", "java.base/java.nio=ALL-UNNAMED", + "--add-opens", "java.base/java.io=ALL-UNNAMED", + "--add-opens", "java.base/java.lang=ALL-UNNAMED", + "--add-opens", "java.base/java.lang.reflect=ALL-UNNAMED", + "--add-opens", "java.base/java.text=ALL-UNNAMED", + "--add-opens", "java.base/java.util=ALL-UNNAMED", + "--add-opens", "java.base/jdk.internal.reflect=ALL-UNNAMED", + "--add-opens", "java.base/sun.nio.ch=ALL-UNNAMED", + "--add-opens", "jdk.naming.dns/com.sun.jndi.dns=ALL-UNNAMED,java.naming", + "--add-opens", "java.desktop/sun.awt.image=ALL-UNNAMED", + "--add-modules", "jdk.dynalink", + "--add-opens", "jdk.dynalink/jdk.dynalink.beans=ALL-UNNAMED", + "--add-modules", "java.sql.rowset", + "--add-opens", "java.sql.rowset/javax.sql.rowset.serial=ALL-UNNAMED" +] + +ext.hotswapJvmArgs = [ + // DCEVM advanced hot reload + "-XX:+AllowEnhancedClassRedefinition", + "-XX:HotswapAgent=fatjar" +] + +ext.setupHotswapAgentTask = tasks.register("setupHotswapAgent") { + group = "GTNH Buildscript" + description = "Installs a recent version of HotSwapAgent into the Java 17 JetBrains runtime directory" + def hsaUrl = 'https://github.com/HotswapProjects/HotswapAgent/releases/download/1.4.2-SNAPSHOT/hotswap-agent-1.4.2-SNAPSHOT.jar' + def targetFolderProvider = javaToolchains.launcherFor(java17Toolchain).map {it.metadata.installationPath.dir("lib/hotswap")} + def targetFilename = "hotswap-agent.jar" + onlyIf { + !targetFolderProvider.get().file(targetFilename).asFile.exists() + } + doLast { + def targetFolder = targetFolderProvider.get() + targetFolder.asFile.mkdirs() + download.run { + src hsaUrl + dest targetFolder.file(targetFilename).asFile + overwrite false + tempAndMove true + } + } +} + +public abstract class RunHotswappableMinecraftTask extends RunMinecraftTask { + // IntelliJ doesn't seem to allow commandline arguments so we also support an env variable + private boolean enableHotswap = Boolean.valueOf(System.getenv("HOTSWAP")); + + @Input + public boolean getEnableHotswap() { return enableHotswap } + @Option(option = "hotswap", description = "Enables HotSwapAgent for enhanced class reloading under a debugger") + public boolean setEnableHotswap(boolean enable) { enableHotswap = enable } + + @Inject + public RunHotswappableMinecraftTask(Distribution side, String superTask, org.gradle.api.invocation.Gradle gradle) { + super(side, gradle) + + this.lwjglVersion = 3 + this.javaLauncher = project.javaToolchains.launcherFor(project.java17Toolchain) + this.extraJvmArgs.addAll(project.java17JvmArgs) + this.extraJvmArgs.addAll(project.provider(() -> enableHotswap ? project.hotswapJvmArgs : [])) + + this.classpath(project.java17PatchDependenciesCfg) + if (side == Distribution.CLIENT) { + this.classpath(project.minecraftTasks.lwjgl3Configuration) + } + // Use a raw provider instead of map to not create a dependency on the task + this.classpath(project.provider(() -> project.tasks.named(superTask, RunMinecraftTask).get().classpath)) + this.classpath.filter { file -> + !file.path.contains("2.9.4-nightly-20150209") // Remove lwjgl2 + } + this.classpath(project.java17DependenciesCfg) + } + + public void setup(Project project) { + super.setup(project) + if (project.usesMixins.toBoolean()) { + this.extraJvmArgs.addAll(project.provider(() -> { + def mixinCfg = project.configurations.detachedConfiguration(project.dependencies.create(project.mixinProviderSpec)) + mixinCfg.canBeConsumed = false + mixinCfg.transitive = false + enableHotswap ? ["-javaagent:" + mixinCfg.singleFile.absolutePath] : [] + })) + } + } +} + +def runClient17Task = tasks.register("runClient17", RunHotswappableMinecraftTask, Distribution.CLIENT, "runClient") +runClient17Task.configure { + setup(project) + group = "Modded Minecraft" + description = "Runs the modded client using Java 17, lwjgl3ify and Hodgepodge" + dependsOn(setupHotswapAgentTask, mcpTasks.launcherSources.classesTaskName, minecraftTasks.taskDownloadVanillaAssets, mcpTasks.taskPackagePatchedMc, 'jar') + mainClass = "GradleStart" + username = minecraft.username + userUUID = minecraft.userUUID +} + +def runServer17Task = tasks.register("runServer17", RunHotswappableMinecraftTask, Distribution.DEDICATED_SERVER, "runServer") +runServer17Task.configure { + setup(project) + group = "Modded Minecraft" + description = "Runs the modded server using Java 17, lwjgl3ify and Hodgepodge" + dependsOn(setupHotswapAgentTask, mcpTasks.launcherSources.classesTaskName, minecraftTasks.taskDownloadVanillaAssets, mcpTasks.taskPackagePatchedMc, 'jar') + mainClass = "GradleStartServer" + extraArgs.add("nogui") +} + def getManifestAttributes() { def manifestAttributes = [:] if (!containsMixinsAndOrCoreModOnly.toBoolean() && (usesMixins.toBoolean() || coreModClass)) { @@ -667,11 +935,6 @@ tasks.named("jar", Jar).configure { } if (usesShadowedDependencies.toBoolean()) { - tasks.register('relocateShadowJar', ConfigureShadowRelocation) { - target = tasks.shadowJar - prefix = modGroup + ".shadow" - enabled = minimizeShadowedDependencies.toBoolean() - } tasks.named("shadowJar", ShadowJar).configure { manifest { attributes(getManifestAttributes()) @@ -686,8 +949,9 @@ if (usesShadowedDependencies.toBoolean()) { project.configurations.shadeCompile ] archiveClassifier.set('dev') - if (minimizeShadowedDependencies.toBoolean()) { - dependsOn(relocateShadowJar) + if (relocateShadowedDependencies.toBoolean()) { + relocationPrefix = modGroup + ".shadow" + enableRelocation = true } } configurations.runtimeElements.outgoing.artifacts.clear() @@ -705,7 +969,7 @@ if (usesShadowedDependencies.toBoolean()) { javaComponent.withVariantsFromConfiguration(configurations.shadowRuntimeElements) { skip() } - for (runTask in ["runClient", "runServer"]) { + for (runTask in ["runClient", "runServer", "runClient17", "runServer17"]) { tasks.named(runTask).configure { dependsOn("shadowJar") } @@ -747,13 +1011,43 @@ idea { } project { settings { + if (ideaOverrideBuildType != "") { + delegateActions { + if ("gradle".equalsIgnoreCase(ideaOverrideBuildType)) { + delegateBuildRunToGradle = true + testRunner = org.jetbrains.gradle.ext.ActionDelegationConfig.TestRunner.GRADLE + } else if ("idea".equalsIgnoreCase(ideaOverrideBuildType)) { + delegateBuildRunToGradle = false + testRunner = org.jetbrains.gradle.ext.ActionDelegationConfig.TestRunner.PLATFORM + } else { + throw GradleScriptException('Accepted value for ideaOverrideBuildType is one of gradle or idea.') + } + } + } runConfigurations { + "0. Build and Test"(Gradle) { + taskNames = ["build"] + } "1. Run Client"(Gradle) { taskNames = ["runClient"] } "2. Run Server"(Gradle) { taskNames = ["runServer"] } + "1a. Run Client (Java 17)"(Gradle) { + taskNames = ["runClient17"] + } + "2a. Run Server (Java 17)"(Gradle) { + taskNames = ["runServer17"] + } + "1b. Run Client (Java 17, Hotswap)"(Gradle) { + taskNames = ["runClient17"] + envs = ["HOTSWAP": "true"] + } + "2b. Run Server (Java 17, Hotswap)"(Gradle) { + taskNames = ["runServer17"] + envs = ["HOTSWAP": "true"] + } "3. Run Obfuscated Client"(Gradle) { taskNames = ["runObfClient"] } @@ -771,7 +1065,7 @@ idea { } "Run Client (IJ Native)"(Application) { mainClass = "GradleStart" - moduleName = project.name + ".main" + moduleName = project.name + ".ideVirtualMain" afterEvaluate { workingDirectory = tasks.runClient.workingDir.absolutePath programParameters = tasks.runClient.calculateArgs(project).collect { '"' + it + '"' }.join(' ') @@ -782,7 +1076,7 @@ idea { } "Run Server (IJ Native)"(Application) { mainClass = "GradleStartServer" - moduleName = project.name + ".main" + moduleName = project.name + ".ideVirtualMain" afterEvaluate { workingDirectory = tasks.runServer.workingDir.absolutePath programParameters = tasks.runServer.calculateArgs(project).collect { '"' + it + '"' }.join(' ') @@ -794,11 +1088,57 @@ idea { } compiler.javac { afterEvaluate { + javacAdditionalOptions = "-encoding utf8" moduleJavacAdditionalOptions = [ (project.name + ".main"): tasks.compileJava.options.compilerArgs.collect { '"' + it + '"' }.join(' ') ] } } + withIDEADir { File ideaDir -> + if (!ideaDir.path.contains(".idea")) { + // If an .ipr file exists, the project root directory is passed here instead of the .idea subdirectory + ideaDir = new File(ideaDir, ".idea") + } + if (ideaDir.isDirectory()) { + def miscFile = new File(ideaDir, "misc.xml") + if (miscFile.isFile()) { + boolean dirty = false + def miscTransformer = new XmlTransformer() + miscTransformer.addAction { root -> + Node rootNode = root.asNode() + def rootManager = rootNode + .component.find { it.@name == 'ProjectRootManager' } + if (!rootManager) { + rootManager = rootNode.appendNode('component', ['name': 'ProjectRootManager', 'version': '2']) + dirty = true + } + def output = rootManager.output + if (!output) { + output = rootManager.appendNode('output') + dirty = true + } + if (!output.@url) { + // Only modify the output url if it doesn't yet have one, or if the existing one is blank somehow. + // This is a sensible default for most setups + output.@url = 'file://$PROJECT_DIR$/build/ideaBuild' + dirty = true + } + } + def result = miscTransformer.transform(miscFile.text) + if (dirty) { + miscFile.write(result) + } + } else { + miscFile.text = """ + + + + + +""" + } + } + } } } } @@ -807,6 +1147,14 @@ tasks.named("processIdeaSettings").configure { dependsOn("injectTags") } +tasks.named("ideVirtualMainClasses").configure { + // Make IntelliJ "Build project" build the mod jars + dependsOn("jar", "reobfJar") + if (!disableSpotless) { + dependsOn("spotlessCheck") + } +} + // workaround variable hiding in pom processing def projectConfigs = project.configurations @@ -827,12 +1175,14 @@ publishing { } repositories { - maven { - url = "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases" - allowInsecureProtocol = true - credentials { - username = System.getenv("MAVEN_USER") ?: "NONE" - password = System.getenv("MAVEN_PASSWORD") ?: "NONE" + if (usesMavenPublishing.toBoolean()) { + maven { + url = mavenPublishUrl + allowInsecureProtocol = mavenPublishUrl.startsWith("http://") // Mostly for the GTNH maven + credentials { + username = System.getenv("MAVEN_USER") ?: "NONE" + password = System.getenv("MAVEN_PASSWORD") ?: "NONE" + } } } } @@ -868,7 +1218,7 @@ if (modrinthProjectId.size() != 0 && System.getenv("MODRINTH_TOKEN") != null) { } } if (usesMixins.toBoolean()) { - addModrinthDep("required", "project", "gtnhmixins") + addModrinthDep("required", "project", "unimixins") } tasks.modrinth.dependsOn(build) tasks.publish.dependsOn(tasks.modrinth) @@ -912,7 +1262,7 @@ if (curseForgeProjectId.size() != 0 && System.getenv("CURSEFORGE_TOKEN") != null } } if (usesMixins.toBoolean()) { - addCurseForgeRelation("requiredDependency", "gtnhmixins") + addCurseForgeRelation("requiredDependency", "unimixins") } tasks.curseforge.dependsOn(build) tasks.publish.dependsOn(tasks.curseforge) @@ -946,10 +1296,21 @@ def addCurseForgeRelation(String type, String name) { } // Updating + +def buildscriptGradleVersion = "8.2.1" + +tasks.named('wrapper', Wrapper).configure { + gradleVersion = buildscriptGradleVersion +} + tasks.register('updateBuildScript') { group = 'GTNH Buildscript' description = 'Updates the build script to the latest version' + if (gradle.gradleVersion != buildscriptGradleVersion && !Boolean.getBoolean('DISABLE_BUILDSCRIPT_GRADLE_UPDATE')) { + dependsOn('wrapper') + } + doLast { if (performBuildScriptUpdate()) return @@ -962,6 +1323,26 @@ if (!project.getGradle().startParameter.isOffline() && !Boolean.getBoolean('DISA performBuildScriptUpdate() } else { out.style(Style.SuccessHeader).println("Build script update available! Run 'gradle updateBuildScript'") + if (gradle.gradleVersion != buildscriptGradleVersion) { + out.style(Style.SuccessHeader).println("updateBuildScript can update gradle from ${gradle.gradleVersion} to ${buildscriptGradleVersion}\n") + } + } +} + +// If you want to add more cases to this task, implement them as arguments if total amount to print gets too large +tasks.register('faq') { + group = 'GTNH Buildscript' + description = 'Prints frequently asked questions about building a project' + + doLast { + print("If your build fails to fetch dependencies, run './gradlew updateDependencies'. " + + "Or you can manually check if the versions are still on the distributing sites - " + + "the links can be found in repositories.gradle and build.gradle:repositories, " + + "but not build.gradle:buildscript.repositories - those ones are for gradle plugin metadata.\n\n" + + "If your build fails to recognize the syntax of new Java versions, enable Jabel in your " + + "gradle.properties. See how it's done in GTNH ExampleMod/gradle.properties. " + + "However, keep in mind that Jabel enables only syntax features, but not APIs that were introduced in " + + "Java 9 or later.") } } @@ -1022,8 +1403,14 @@ boolean isNewBuildScriptVersionAvailable() { String currentBuildScript = getFile("build.gradle").getText() String currentBuildScriptHash = getVersionHash(currentBuildScript) - String availableBuildScript = availableBuildScriptUrl().newInputStream(parameters).getText() - String availableBuildScriptHash = getVersionHash(availableBuildScript) + String availableBuildScriptHash + try { + String availableBuildScript = availableBuildScriptUrl().newInputStream(parameters).getText() + availableBuildScriptHash = getVersionHash(availableBuildScript) + } catch (IOException e) { + logger.warn("Could not check for buildscript update availability: {}", e.message) + return false + } boolean isUpToDate = currentBuildScriptHash.empty || availableBuildScriptHash.empty || currentBuildScriptHash == availableBuildScriptHash return !isUpToDate @@ -1102,7 +1489,7 @@ static int replaceParams(File file, Map params) { return 0 } -// Dependency Deobfuscation +// Dependency Deobfuscation (Deprecated, use the new RFG API documented in dependencies.gradle) def deobf(String sourceURL) { try { @@ -1144,11 +1531,7 @@ def deobfMaven(String repoURL, String mavenDep) { } def deobfCurse(String curseDep) { - try { - return deobfMaven("https://www.cursemaven.com/", "curse.maven:$curseDep") - } catch (Exception ignored) { - out.style(Style.Failure).println("Failed to get $curseDep from cursemaven.") - } + return dependencies.rfg.deobf("curse.maven:$curseDep") } // The method above is to be preferred. Use this method if the filename is not at the end of the URL. @@ -1156,34 +1539,7 @@ 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 - String remoteMappings = project.hasProperty('remoteMappings') ? project.remoteMappings : 'https://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/' - 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 @@ -1191,50 +1547,8 @@ def deobf(String sourceURL, String rawFileName) { 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() + return dependencies.rfg.deobf(files(obfFile)) } - // Helper methods def checkPropertyExists(String propertyName) { @@ -1261,3 +1575,17 @@ def getSecondaryArtifacts() { if (apiPackage) secondaryArtifacts += [apiJar] return secondaryArtifacts } + +// For easier scripting of things that require variables defined earlier in the buildscript +if (file('addon.late.gradle.kts').exists()) { + apply from: 'addon.late.gradle.kts' +} else if (file('addon.late.gradle').exists()) { + apply from: 'addon.late.gradle' +} + +// File for local tweaks not commited to Git +if (file('addon.late.local.gradle.kts').exists()) { + apply from: 'addon.late.local.gradle.kts' +} else if (file('addon.late.local.gradle').exists()) { + apply from: 'addon.late.local.gradle' +} diff --git a/dependencies.gradle b/dependencies.gradle index 1967ff5..a5ffc0b 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,11 +1,13 @@ // Add your dependencies here dependencies { - compile("com.github.GTNewHorizons:CodeChickenLib:1.1.5.7:dev") - compileOnly("com.github.GTNewHorizons:Natura:2.5.5:dev") { + compileOnly("com.github.GTNewHorizons:CodeChickenLib:1.1.8:dev") + compileOnly("com.github.GTNewHorizons:Natura:2.5.7:dev") { transitive = false } compileOnly("curse.maven:pams-harvestcraft-221857:2270206") { transitive = false } + + runtimeOnlyNonPublishable("com.github.GTNewHorizons:NotEnoughItems:2.3.83-GTNH:dev") } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index ccebba7..943f0cb 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f398c33..17a8ddc 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 79a61d4..65dcd68 100755 --- a/gradlew +++ b/gradlew @@ -144,7 +144,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +152,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac diff --git a/repositories.gradle b/repositories.gradle index 80174d7..c227b16 100644 --- a/repositories.gradle +++ b/repositories.gradle @@ -1,15 +1,4 @@ // Add any additional repositories for your dependencies here repositories { - maven { - name = "GTNH Maven" - url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" - } - maven { - url "https://cursemaven.com" - } - maven { - name = "jitpack.io" - url = "https://jitpack.io" - } } diff --git a/src/main/java/squeek/applecore/AppleCore.java b/src/main/java/squeek/applecore/AppleCore.java index 0209240..394d0b7 100644 --- a/src/main/java/squeek/applecore/AppleCore.java +++ b/src/main/java/squeek/applecore/AppleCore.java @@ -12,16 +12,6 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import squeek.applecore.api_impl.AppleCoreAccessorMutatorImpl; -import squeek.applecore.api_impl.AppleCoreDispatcherImpl; -import squeek.applecore.api_impl.AppleCoreRegistryImpl; -import squeek.applecore.client.DebugInfoHandler; -import squeek.applecore.client.HUDOverlayHandler; -import squeek.applecore.client.TooltipOverlayHandler; -import squeek.applecore.commands.Commands; -import squeek.applecore.mixinplugin.Mixins; -import squeek.applecore.network.SyncHandler; - import com.gtnewhorizon.gtnhmixins.IEarlyMixinLoader; import cpw.mods.fml.client.event.ConfigChangedEvent; @@ -34,6 +24,15 @@ import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.relauncher.IFMLLoadingPlugin; import cpw.mods.fml.relauncher.Side; +import squeek.applecore.api_impl.AppleCoreAccessorMutatorImpl; +import squeek.applecore.api_impl.AppleCoreDispatcherImpl; +import squeek.applecore.api_impl.AppleCoreRegistryImpl; +import squeek.applecore.client.DebugInfoHandler; +import squeek.applecore.client.HUDOverlayHandler; +import squeek.applecore.client.TooltipOverlayHandler; +import squeek.applecore.commands.Commands; +import squeek.applecore.mixinplugin.Mixins; +import squeek.applecore.network.SyncHandler; @IFMLLoadingPlugin.SortingIndex(1100) @IFMLLoadingPlugin.MCVersion("1.7.10") diff --git a/src/main/java/squeek/applecore/api/food/FoodEvent.java b/src/main/java/squeek/applecore/api/food/FoodEvent.java index 80f074e..504e0db 100644 --- a/src/main/java/squeek/applecore/api/food/FoodEvent.java +++ b/src/main/java/squeek/applecore/api/food/FoodEvent.java @@ -8,9 +8,9 @@ import net.minecraft.util.FoodStats; import net.minecraftforge.common.MinecraftForge; -import squeek.applecore.api.AppleCoreAPI; import cpw.mods.fml.common.eventhandler.Cancelable; import cpw.mods.fml.common.eventhandler.Event; +import squeek.applecore.api.AppleCoreAPI; /** * Base class for all FoodEvent events.
diff --git a/src/main/java/squeek/applecore/api/hunger/ExhaustionEvent.java b/src/main/java/squeek/applecore/api/hunger/ExhaustionEvent.java index cc6729a..0754c22 100644 --- a/src/main/java/squeek/applecore/api/hunger/ExhaustionEvent.java +++ b/src/main/java/squeek/applecore/api/hunger/ExhaustionEvent.java @@ -8,9 +8,9 @@ import net.minecraft.world.EnumDifficulty; import net.minecraftforge.common.MinecraftForge; -import squeek.applecore.api.AppleCoreAPI; import cpw.mods.fml.common.eventhandler.Cancelable; import cpw.mods.fml.common.eventhandler.Event; +import squeek.applecore.api.AppleCoreAPI; /** * Base class for all ExhaustionEvent events.
diff --git a/src/main/java/squeek/applecore/api/hunger/HealthRegenEvent.java b/src/main/java/squeek/applecore/api/hunger/HealthRegenEvent.java index 9b5af87..6b2100a 100644 --- a/src/main/java/squeek/applecore/api/hunger/HealthRegenEvent.java +++ b/src/main/java/squeek/applecore/api/hunger/HealthRegenEvent.java @@ -7,9 +7,9 @@ import net.minecraft.util.FoodStats; import net.minecraftforge.common.MinecraftForge; -import squeek.applecore.api.AppleCoreAPI; import cpw.mods.fml.common.eventhandler.Cancelable; import cpw.mods.fml.common.eventhandler.Event; +import squeek.applecore.api.AppleCoreAPI; /** * Base class for all HealthRegenEvent events.
diff --git a/src/main/java/squeek/applecore/api/hunger/StarvationEvent.java b/src/main/java/squeek/applecore/api/hunger/StarvationEvent.java index 9029339..9d22227 100644 --- a/src/main/java/squeek/applecore/api/hunger/StarvationEvent.java +++ b/src/main/java/squeek/applecore/api/hunger/StarvationEvent.java @@ -8,9 +8,9 @@ import net.minecraft.world.EnumDifficulty; import net.minecraftforge.common.MinecraftForge; -import squeek.applecore.api.AppleCoreAPI; import cpw.mods.fml.common.eventhandler.Cancelable; import cpw.mods.fml.common.eventhandler.Event; +import squeek.applecore.api.AppleCoreAPI; /** * Base class for all StarvationEvent events.
diff --git a/src/main/java/squeek/applecore/api/package-info.java b/src/main/java/squeek/applecore/api/package-info.java index 376e18d..f0f939a 100644 --- a/src/main/java/squeek/applecore/api/package-info.java +++ b/src/main/java/squeek/applecore/api/package-info.java @@ -1,5 +1,5 @@ @API(apiVersion = ModInfo.APIVERSION, owner = ModInfo.MODID, provides = ModInfo.MODAPI) package squeek.applecore.api; -import squeek.applecore.ModInfo; import cpw.mods.fml.common.API; +import squeek.applecore.ModInfo; diff --git a/src/main/java/squeek/applecore/api_impl/AppleCoreDispatcherImpl.java b/src/main/java/squeek/applecore/api_impl/AppleCoreDispatcherImpl.java index 9b26097..2a3d98c 100644 --- a/src/main/java/squeek/applecore/api_impl/AppleCoreDispatcherImpl.java +++ b/src/main/java/squeek/applecore/api_impl/AppleCoreDispatcherImpl.java @@ -6,10 +6,10 @@ import net.minecraft.world.World; import net.minecraftforge.common.MinecraftForge; +import cpw.mods.fml.common.eventhandler.Event; import squeek.applecore.api.AppleCoreAPI; import squeek.applecore.api.IAppleCoreDispatcher; import squeek.applecore.api.plants.PlantGrowthEvent; -import cpw.mods.fml.common.eventhandler.Event; public enum AppleCoreDispatcherImpl implements IAppleCoreDispatcher { diff --git a/src/main/java/squeek/applecore/client/DebugInfoHandler.java b/src/main/java/squeek/applecore/client/DebugInfoHandler.java index fe9d176..bab551a 100644 --- a/src/main/java/squeek/applecore/client/DebugInfoHandler.java +++ b/src/main/java/squeek/applecore/client/DebugInfoHandler.java @@ -7,11 +7,11 @@ import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.common.MinecraftForge; -import squeek.applecore.ModConfig; -import squeek.applecore.api.AppleCoreAPI; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; +import squeek.applecore.ModConfig; +import squeek.applecore.api.AppleCoreAPI; @SideOnly(Side.CLIENT) public class DebugInfoHandler { diff --git a/src/main/java/squeek/applecore/client/HUDOverlayHandler.java b/src/main/java/squeek/applecore/client/HUDOverlayHandler.java index 5392aa2..3b6f9b7 100644 --- a/src/main/java/squeek/applecore/client/HUDOverlayHandler.java +++ b/src/main/java/squeek/applecore/client/HUDOverlayHandler.java @@ -14,10 +14,6 @@ import org.lwjgl.opengl.GL11; -import squeek.applecore.ModConfig; -import squeek.applecore.ModInfo; -import squeek.applecore.api.AppleCoreAPI; -import squeek.applecore.api.food.FoodValues; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.eventhandler.EventPriority; import cpw.mods.fml.common.eventhandler.SubscribeEvent; @@ -25,6 +21,10 @@ import cpw.mods.fml.common.gameevent.TickEvent.ClientTickEvent; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; +import squeek.applecore.ModConfig; +import squeek.applecore.ModInfo; +import squeek.applecore.api.AppleCoreAPI; +import squeek.applecore.api.food.FoodValues; @SideOnly(Side.CLIENT) public class HUDOverlayHandler { diff --git a/src/main/java/squeek/applecore/client/TooltipOverlayHandler.java b/src/main/java/squeek/applecore/client/TooltipOverlayHandler.java index 070e18c..68de33d 100644 --- a/src/main/java/squeek/applecore/client/TooltipOverlayHandler.java +++ b/src/main/java/squeek/applecore/client/TooltipOverlayHandler.java @@ -16,12 +16,6 @@ import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; -import squeek.applecore.AppleCore; -import squeek.applecore.ModConfig; -import squeek.applecore.ModInfo; -import squeek.applecore.api.AppleCoreAPI; -import squeek.applecore.api.food.FoodValues; -import squeek.applecore.helpers.KeyHelper; import cpw.mods.fml.common.Loader; import cpw.mods.fml.common.ObfuscationReflectionHelper; import cpw.mods.fml.common.eventhandler.SubscribeEvent; @@ -30,6 +24,12 @@ import cpw.mods.fml.relauncher.ReflectionHelper; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; +import squeek.applecore.AppleCore; +import squeek.applecore.ModConfig; +import squeek.applecore.ModInfo; +import squeek.applecore.api.AppleCoreAPI; +import squeek.applecore.api.food.FoodValues; +import squeek.applecore.helpers.KeyHelper; @SideOnly(Side.CLIENT) public class TooltipOverlayHandler { diff --git a/src/main/java/squeek/applecore/client/gui/GuiAppleCoreConfig.java b/src/main/java/squeek/applecore/client/gui/GuiAppleCoreConfig.java index ba97c76..28bdc8d 100644 --- a/src/main/java/squeek/applecore/client/gui/GuiAppleCoreConfig.java +++ b/src/main/java/squeek/applecore/client/gui/GuiAppleCoreConfig.java @@ -5,10 +5,10 @@ import net.minecraft.client.gui.GuiScreen; import net.minecraftforge.common.config.ConfigElement; -import squeek.applecore.ModConfig; -import squeek.applecore.ModInfo; import cpw.mods.fml.client.config.GuiConfig; import cpw.mods.fml.client.config.IConfigElement; +import squeek.applecore.ModConfig; +import squeek.applecore.ModInfo; public class GuiAppleCoreConfig extends GuiConfig { diff --git a/src/main/java/squeek/applecore/mixinplugin/AppleCoreLateMixins.java b/src/main/java/squeek/applecore/mixinplugin/AppleCoreLateMixins.java index cc07b7d..9e8cc90 100644 --- a/src/main/java/squeek/applecore/mixinplugin/AppleCoreLateMixins.java +++ b/src/main/java/squeek/applecore/mixinplugin/AppleCoreLateMixins.java @@ -5,11 +5,11 @@ import java.util.List; import java.util.Set; -import squeek.applecore.AppleCore; - import com.gtnewhorizon.gtnhmixins.ILateMixinLoader; import com.gtnewhorizon.gtnhmixins.LateMixin; +import squeek.applecore.AppleCore; + @LateMixin public class AppleCoreLateMixins implements ILateMixinLoader { diff --git a/src/main/java/squeek/applecore/mixins/early/codechickenlib/GuiDrawMixin.java b/src/main/java/squeek/applecore/mixins/early/codechickenlib/GuiDrawMixin.java index eb15cbd..cae2e07 100644 --- a/src/main/java/squeek/applecore/mixins/early/codechickenlib/GuiDrawMixin.java +++ b/src/main/java/squeek/applecore/mixins/early/codechickenlib/GuiDrawMixin.java @@ -5,8 +5,8 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import squeek.applecore.client.TooltipOverlayHandler; import codechicken.lib.gui.GuiDraw; +import squeek.applecore.client.TooltipOverlayHandler; @Mixin(GuiDraw.class) public class GuiDrawMixin { diff --git a/src/main/java/squeek/applecore/mixins/early/minecraft/BlockCactusMixin.java b/src/main/java/squeek/applecore/mixins/early/minecraft/BlockCactusMixin.java index c504b9d..8c26a18 100644 --- a/src/main/java/squeek/applecore/mixins/early/minecraft/BlockCactusMixin.java +++ b/src/main/java/squeek/applecore/mixins/early/minecraft/BlockCactusMixin.java @@ -10,8 +10,8 @@ import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; -import squeek.applecore.api.AppleCoreAPI; import cpw.mods.fml.common.eventhandler.Event; +import squeek.applecore.api.AppleCoreAPI; @Mixin(BlockCactus.class) public abstract class BlockCactusMixin extends Block { diff --git a/src/main/java/squeek/applecore/mixins/early/minecraft/BlockCocoaMixin.java b/src/main/java/squeek/applecore/mixins/early/minecraft/BlockCocoaMixin.java index 2ec1b93..f02afc5 100644 --- a/src/main/java/squeek/applecore/mixins/early/minecraft/BlockCocoaMixin.java +++ b/src/main/java/squeek/applecore/mixins/early/minecraft/BlockCocoaMixin.java @@ -9,8 +9,8 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; -import squeek.applecore.api.AppleCoreAPI; import cpw.mods.fml.common.eventhandler.Event; +import squeek.applecore.api.AppleCoreAPI; @Mixin(BlockCocoa.class) public abstract class BlockCocoaMixin extends BlockDirectional { diff --git a/src/main/java/squeek/applecore/mixins/early/minecraft/BlockCropsMixin.java b/src/main/java/squeek/applecore/mixins/early/minecraft/BlockCropsMixin.java index 113809a..5b2e7b1 100644 --- a/src/main/java/squeek/applecore/mixins/early/minecraft/BlockCropsMixin.java +++ b/src/main/java/squeek/applecore/mixins/early/minecraft/BlockCropsMixin.java @@ -10,8 +10,8 @@ import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; -import squeek.applecore.api.AppleCoreAPI; import cpw.mods.fml.common.eventhandler.Event; +import squeek.applecore.api.AppleCoreAPI; @Mixin(BlockCrops.class) public class BlockCropsMixin extends BlockBush { diff --git a/src/main/java/squeek/applecore/mixins/early/minecraft/BlockMushroomMixin.java b/src/main/java/squeek/applecore/mixins/early/minecraft/BlockMushroomMixin.java index 47f0bc2..72e1bb6 100644 --- a/src/main/java/squeek/applecore/mixins/early/minecraft/BlockMushroomMixin.java +++ b/src/main/java/squeek/applecore/mixins/early/minecraft/BlockMushroomMixin.java @@ -13,8 +13,8 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import squeek.applecore.api.AppleCoreAPI; import cpw.mods.fml.common.eventhandler.Event; +import squeek.applecore.api.AppleCoreAPI; @Mixin(BlockMushroom.class) public class BlockMushroomMixin extends BlockBush { diff --git a/src/main/java/squeek/applecore/mixins/early/minecraft/BlockNetherWartMixin.java b/src/main/java/squeek/applecore/mixins/early/minecraft/BlockNetherWartMixin.java index e454040..27151a9 100644 --- a/src/main/java/squeek/applecore/mixins/early/minecraft/BlockNetherWartMixin.java +++ b/src/main/java/squeek/applecore/mixins/early/minecraft/BlockNetherWartMixin.java @@ -9,8 +9,8 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; -import squeek.applecore.api.AppleCoreAPI; import cpw.mods.fml.common.eventhandler.Event; +import squeek.applecore.api.AppleCoreAPI; @Mixin(BlockNetherWart.class) public class BlockNetherWartMixin extends BlockBush { diff --git a/src/main/java/squeek/applecore/mixins/early/minecraft/BlockReedMixin.java b/src/main/java/squeek/applecore/mixins/early/minecraft/BlockReedMixin.java index 85bbe0c..985ad16 100644 --- a/src/main/java/squeek/applecore/mixins/early/minecraft/BlockReedMixin.java +++ b/src/main/java/squeek/applecore/mixins/early/minecraft/BlockReedMixin.java @@ -12,8 +12,8 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import squeek.applecore.api.AppleCoreAPI; import cpw.mods.fml.common.eventhandler.Event; +import squeek.applecore.api.AppleCoreAPI; @Mixin(BlockReed.class) public class BlockReedMixin extends Block { diff --git a/src/main/java/squeek/applecore/mixins/early/minecraft/BlockSaplingMixin.java b/src/main/java/squeek/applecore/mixins/early/minecraft/BlockSaplingMixin.java index f487df0..a888f1c 100644 --- a/src/main/java/squeek/applecore/mixins/early/minecraft/BlockSaplingMixin.java +++ b/src/main/java/squeek/applecore/mixins/early/minecraft/BlockSaplingMixin.java @@ -12,8 +12,8 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import squeek.applecore.api.AppleCoreAPI; import cpw.mods.fml.common.eventhandler.Event; +import squeek.applecore.api.AppleCoreAPI; @Mixin(BlockSapling.class) public abstract class BlockSaplingMixin extends BlockBush { diff --git a/src/main/java/squeek/applecore/mixins/early/minecraft/BlockStemMixin.java b/src/main/java/squeek/applecore/mixins/early/minecraft/BlockStemMixin.java index fcef02f..09f2b22 100644 --- a/src/main/java/squeek/applecore/mixins/early/minecraft/BlockStemMixin.java +++ b/src/main/java/squeek/applecore/mixins/early/minecraft/BlockStemMixin.java @@ -13,8 +13,8 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import squeek.applecore.api.AppleCoreAPI; import cpw.mods.fml.common.eventhandler.Event; +import squeek.applecore.api.AppleCoreAPI; @Mixin(BlockStem.class) public class BlockStemMixin extends BlockBush { diff --git a/src/main/java/squeek/applecore/mixins/early/minecraft/EntityPlayerMixin.java b/src/main/java/squeek/applecore/mixins/early/minecraft/EntityPlayerMixin.java index 1a75153..3cdc8a4 100644 --- a/src/main/java/squeek/applecore/mixins/early/minecraft/EntityPlayerMixin.java +++ b/src/main/java/squeek/applecore/mixins/early/minecraft/EntityPlayerMixin.java @@ -16,14 +16,13 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import squeek.applecore.api.hunger.HealthRegenEvent; -import squeek.applecore.mixinplugin.ducks.EntityPlayerExt; -import squeek.applecore.mixinplugin.ducks.FoodStatsExt; - import com.mojang.authlib.GameProfile; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; +import squeek.applecore.api.hunger.HealthRegenEvent; +import squeek.applecore.mixinplugin.ducks.EntityPlayerExt; +import squeek.applecore.mixinplugin.ducks.FoodStatsExt; @Mixin(EntityPlayer.class) public abstract class EntityPlayerMixin extends EntityLivingBase implements EntityPlayerExt { diff --git a/src/main/java/squeek/applecore/mixins/early/minecraft/FoodStatsMixin.java b/src/main/java/squeek/applecore/mixins/early/minecraft/FoodStatsMixin.java index 90ec23c..8cbf1c6 100644 --- a/src/main/java/squeek/applecore/mixins/early/minecraft/FoodStatsMixin.java +++ b/src/main/java/squeek/applecore/mixins/early/minecraft/FoodStatsMixin.java @@ -1,5 +1,7 @@ package squeek.applecore.mixins.early.minecraft; +import java.lang.reflect.Field; + import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemFood; import net.minecraft.item.ItemStack; @@ -15,6 +17,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import cpw.mods.fml.common.eventhandler.Event; import squeek.applecore.api.AppleCoreAPI; import squeek.applecore.api.food.FoodEvent; import squeek.applecore.api.food.FoodValues; @@ -22,11 +25,13 @@ import squeek.applecore.api.hunger.HealthRegenEvent; import squeek.applecore.api.hunger.StarvationEvent; import squeek.applecore.mixinplugin.ducks.FoodStatsExt; -import cpw.mods.fml.common.eventhandler.Event; @Mixin(FoodStats.class) public abstract class FoodStatsMixin implements FoodStatsExt { + private static Field fieldEntityPlayer; + private static boolean searchedFieldEntityPlayer; + @Unique private EntityPlayer entityPlayer; @@ -66,7 +71,7 @@ public void setPlayer(EntityPlayer entityPlayer) { @Inject(method = "addStats", at = @At("HEAD"), cancellable = true) private void onAddStats(int hunger, float saturationModifier, CallbackInfo callbackInfo) { FoodEvent.FoodStatsAddition event = new FoodEvent.FoodStatsAddition( - entityPlayer, + appleCore$getEntityPlayer(), new FoodValues(hunger, saturationModifier)); MinecraftForge.EVENT_BUS.post(event); if (event.isCancelable() && event.isCanceled()) { @@ -80,7 +85,8 @@ private void onAddStats(int hunger, float saturationModifier, CallbackInfo callb */ @Overwrite public void func_151686_a(ItemFood itemFood, ItemStack itemStack) { - FoodValues modifiedFoodValues = AppleCoreAPI.accessor.getFoodValuesForPlayer(itemStack, entityPlayer); + FoodValues modifiedFoodValues = AppleCoreAPI.accessor + .getFoodValuesForPlayer(itemStack, appleCore$getEntityPlayer()); int prevFoodLevel = foodLevel; float prevSaturationLevel = foodSaturationLevel; @@ -88,7 +94,7 @@ public void func_151686_a(ItemFood itemFood, ItemStack itemStack) { MinecraftForge.EVENT_BUS.post( new FoodEvent.FoodEaten( - entityPlayer, + appleCore$getEntityPlayer(), itemStack, modifiedFoodValues, foodLevel - prevFoodLevel, @@ -162,4 +168,37 @@ public void onUpdate(EntityPlayer player) { starveTimer = 0; } } + + @Unique + private EntityPlayer appleCore$getEntityPlayer() { + if (!searchedFieldEntityPlayer) { + try { + // noinspection JavaReflectionMemberAccess + fieldEntityPlayer = FoodStats.class.getDeclaredField("entityplayer"); + fieldEntityPlayer.setAccessible(true); + } catch (NoSuchFieldException ignored) {} + searchedFieldEntityPlayer = true; + } + + // Thermos strikes again: EntityPlayer#foodStats might be reassigned by Thermos's patch EntityPlayerMP#reset(), + // which means `FoodStats` might be initialized outside `EntityPlayer` constructor + // (where AppleCore injects `redirectNewFoodStats`), thus our field `entityPlayer` can be null. + // Here we try to access Thermos's own field `entityplayer` and return non-null player. + + if (entityPlayer != null) { + return entityPlayer; + } + if (fieldEntityPlayer != null) { + try { + Object thermosEntityPlayer = fieldEntityPlayer.get(this); + if (thermosEntityPlayer instanceof EntityPlayer) { + this.entityPlayer = (EntityPlayer) thermosEntityPlayer; + return entityPlayer; + } + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + throw new RuntimeException("Cannot find non-null EntityPlayer that should belong to FoodStats"); + } } diff --git a/src/main/java/squeek/applecore/mixins/late/harvestcraft/BlockPamFruitMixin.java b/src/main/java/squeek/applecore/mixins/late/harvestcraft/BlockPamFruitMixin.java index 1fd1fb4..daa9141 100644 --- a/src/main/java/squeek/applecore/mixins/late/harvestcraft/BlockPamFruitMixin.java +++ b/src/main/java/squeek/applecore/mixins/late/harvestcraft/BlockPamFruitMixin.java @@ -7,10 +7,10 @@ import org.spongepowered.asm.mixin.Mixin; -import squeek.applecore.api.AppleCoreAPI; - import com.pam.harvestcraft.BlockPamFruit; + import cpw.mods.fml.common.eventhandler.Event; +import squeek.applecore.api.AppleCoreAPI; @Mixin(BlockPamFruit.class) public class BlockPamFruitMixin extends Block { diff --git a/src/main/java/squeek/applecore/mixins/late/harvestcraft/BlockPamSaplingMixin.java b/src/main/java/squeek/applecore/mixins/late/harvestcraft/BlockPamSaplingMixin.java index 6926531..80f035c 100644 --- a/src/main/java/squeek/applecore/mixins/late/harvestcraft/BlockPamSaplingMixin.java +++ b/src/main/java/squeek/applecore/mixins/late/harvestcraft/BlockPamSaplingMixin.java @@ -8,10 +8,10 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import squeek.applecore.api.AppleCoreAPI; - import com.pam.harvestcraft.BlockPamSapling; + import cpw.mods.fml.common.eventhandler.Event; +import squeek.applecore.api.AppleCoreAPI; @Mixin(BlockPamSapling.class) public abstract class BlockPamSaplingMixin extends BlockFlower { diff --git a/src/main/java/squeek/applecore/mixins/late/natura/BerryBushMixin.java b/src/main/java/squeek/applecore/mixins/late/natura/BerryBushMixin.java index 2f98f7f..b6823d9 100644 --- a/src/main/java/squeek/applecore/mixins/late/natura/BerryBushMixin.java +++ b/src/main/java/squeek/applecore/mixins/late/natura/BerryBushMixin.java @@ -2,16 +2,15 @@ import java.util.Random; -import mods.natura.blocks.crops.BerryBush; - import net.minecraft.block.BlockLeavesBase; import net.minecraft.init.Blocks; import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; -import squeek.applecore.api.AppleCoreAPI; import cpw.mods.fml.common.eventhandler.Event; +import mods.natura.blocks.crops.BerryBush; +import squeek.applecore.api.AppleCoreAPI; @Mixin(BerryBush.class) public class BerryBushMixin extends BlockLeavesBase { diff --git a/src/main/java/squeek/applecore/mixins/late/natura/CropBlockMixin.java b/src/main/java/squeek/applecore/mixins/late/natura/CropBlockMixin.java index c60e187..69397a9 100644 --- a/src/main/java/squeek/applecore/mixins/late/natura/CropBlockMixin.java +++ b/src/main/java/squeek/applecore/mixins/late/natura/CropBlockMixin.java @@ -2,16 +2,15 @@ import java.util.Random; -import mods.natura.blocks.crops.CropBlock; - import net.minecraft.block.BlockBush; import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import squeek.applecore.api.AppleCoreAPI; import cpw.mods.fml.common.eventhandler.Event; +import mods.natura.blocks.crops.CropBlock; +import squeek.applecore.api.AppleCoreAPI; @Mixin(CropBlock.class) public abstract class CropBlockMixin extends BlockBush { diff --git a/src/main/java/squeek/applecore/mixins/late/natura/GlowshroomMixin.java b/src/main/java/squeek/applecore/mixins/late/natura/GlowshroomMixin.java index e8ed360..fd25078 100644 --- a/src/main/java/squeek/applecore/mixins/late/natura/GlowshroomMixin.java +++ b/src/main/java/squeek/applecore/mixins/late/natura/GlowshroomMixin.java @@ -2,8 +2,6 @@ import java.util.Random; -import mods.natura.blocks.crops.Glowshroom; - import net.minecraft.block.BlockMushroom; import net.minecraft.world.World; @@ -14,8 +12,9 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import squeek.applecore.api.AppleCoreAPI; import cpw.mods.fml.common.eventhandler.Event; +import mods.natura.blocks.crops.Glowshroom; +import squeek.applecore.api.AppleCoreAPI; @Mixin(Glowshroom.class) public class GlowshroomMixin extends BlockMushroom { diff --git a/src/main/java/squeek/applecore/mixins/late/natura/NetherBerryBushMixin.java b/src/main/java/squeek/applecore/mixins/late/natura/NetherBerryBushMixin.java index 32764f7..94989a6 100644 --- a/src/main/java/squeek/applecore/mixins/late/natura/NetherBerryBushMixin.java +++ b/src/main/java/squeek/applecore/mixins/late/natura/NetherBerryBushMixin.java @@ -2,16 +2,15 @@ import java.util.Random; -import mods.natura.blocks.crops.NetherBerryBush; - import net.minecraft.block.BlockLeavesBase; import net.minecraft.init.Blocks; import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; -import squeek.applecore.api.AppleCoreAPI; import cpw.mods.fml.common.eventhandler.Event; +import mods.natura.blocks.crops.NetherBerryBush; +import squeek.applecore.api.AppleCoreAPI; @Mixin(NetherBerryBush.class) public class NetherBerryBushMixin extends BlockLeavesBase { diff --git a/src/main/java/squeek/applecore/network/MessageExhaustionSync.java b/src/main/java/squeek/applecore/network/MessageExhaustionSync.java index 2bac62f..42e1995 100644 --- a/src/main/java/squeek/applecore/network/MessageExhaustionSync.java +++ b/src/main/java/squeek/applecore/network/MessageExhaustionSync.java @@ -1,10 +1,10 @@ package squeek.applecore.network; -import squeek.applecore.api.AppleCoreAPI; import cpw.mods.fml.common.network.simpleimpl.IMessage; import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; import cpw.mods.fml.common.network.simpleimpl.MessageContext; import io.netty.buffer.ByteBuf; +import squeek.applecore.api.AppleCoreAPI; public class MessageExhaustionSync implements IMessage, IMessageHandler { diff --git a/src/main/java/squeek/applecore/network/SyncHandler.java b/src/main/java/squeek/applecore/network/SyncHandler.java index 96df777..8e93348 100644 --- a/src/main/java/squeek/applecore/network/SyncHandler.java +++ b/src/main/java/squeek/applecore/network/SyncHandler.java @@ -10,9 +10,6 @@ import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent; -import squeek.applecore.ModConfig; -import squeek.applecore.ModInfo; -import squeek.applecore.api.AppleCoreAPI; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.common.gameevent.PlayerEvent; @@ -21,6 +18,9 @@ import cpw.mods.fml.common.network.NetworkRegistry; import cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper; import cpw.mods.fml.relauncher.Side; +import squeek.applecore.ModConfig; +import squeek.applecore.ModInfo; +import squeek.applecore.api.AppleCoreAPI; public class SyncHandler {