diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..4ffbd90 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,22 @@ +# 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 + +[*.lang] +trim_trailing_whitespace = false diff --git a/.github/scripts/test_no_error_reports b/.github/scripts/test_no_error_reports new file mode 100644 index 0000000..1fcc739 --- /dev/null +++ b/.github/scripts/test_no_error_reports @@ -0,0 +1,51 @@ +#!/usr/bin/env bash + +# bashsupport disable=BP5006 # Global environment variables +RUNDIR="run" \ + CRASH="crash-reports" \ + SERVERLOG="server.log" + +# enable nullglob to get 0 results when no match rather than the pattern +shopt -s nullglob + +# store matches in array +crash_reports=("$RUNDIR/$CRASH/crash"*.txt) + +# if array not empty there are crash_reports +if [ "${#crash_reports[@]}" -gt 0 ]; then + # get the latest crash_report from array + latest_crash_report="${crash_reports[-1]}" + { + printf 'Latest crash report detected %s:\n' "${latest_crash_report##*/}" + cat "$latest_crash_report" + } >&2 + exit 1 +fi + +if grep --quiet --fixed-strings 'Fatal errors were detected' "$SERVERLOG"; then + { + printf 'Fatal errors detected:\n' + cat server.log + } >&2 + exit 1 +fi + +if grep --quiet --fixed-strings 'The state engine was in incorrect state ERRORED and forced into state SERVER_STOPPED' \ + "$SERVERLOG"; then + { + printf 'Server force stopped:' + cat server.log + } >&2 + exit 1 +fi + +if ! grep --quiet --perl-regexp --only-matching '.+Done \(.+\)\! For help, type "help" or "\?"' "$SERVERLOG"; then + { + printf 'Server did not finish startup:' + cat server.log + } >&2 + exit 1 +fi + +printf 'No crash reports detected' +exit 0 diff --git a/.github/scripts/update_version b/.github/scripts/update_version new file mode 100644 index 0000000..3e5f752 --- /dev/null +++ b/.github/scripts/update_version @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +if ! git diff --name-only HEAD HEAD~1 | grep -qF 'build.gradle'; then + new_version="$(date +%s)" + sed --in-place "s!^//version:.*!//version: $new_version!g" build.gradle + git add build.gradle + git commit -m "[ci skip] update build script version to $new_version" + git push + printf 'Updated buildscript version to %s\n' "$new_version" +else + printf 'Ignored buildscript version update: no changes detected\n' +fi diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml new file mode 100644 index 0000000..56a1ad5 --- /dev/null +++ b/.github/workflows/build-and-test.yml @@ -0,0 +1,45 @@ +# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle + +name: Build and test + +on: + pull_request: + branches: [ master, main ] + push: + branches: [ master, main ] + +jobs: + build-and-test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Set up JDK 8 + uses: actions/setup-java@v2 + with: + java-version: '8' + distribution: 'adopt' + cache: gradle + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Setup the workspace + run: ./gradlew setupCIWorkspace + + - name: Build the mod + run: ./gradlew build + + - name: Run server for 1.5 minutes + run: | + mkdir run + echo "eula=true" > run/eula.txt + timeout 90 ./gradlew runServer 2>&1 | tee -a server.log || true + + - name: Test no errors reported during server run + run: | + chmod +x .github/scripts/test_no_error_reports + .github/scripts/test_no_error_reports diff --git a/.github/workflows/release-tags.yml b/.github/workflows/release-tags.yml new file mode 100644 index 0000000..c86d888 --- /dev/null +++ b/.github/workflows/release-tags.yml @@ -0,0 +1,51 @@ +# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle + +name: Release tagged build + +on: + push: + tags: + - '*' + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Set release version + run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV + + - name: Set up JDK 8 + uses: actions/setup-java@v2 + with: + java-version: '8' + distribution: 'adopt' + cache: gradle + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Setup the workspace + run: ./gradlew setupCIWorkspace + + - name: Build the mod + run: ./gradlew build + + - name: Release under current tag + uses: "marvinpinto/action-automatic-releases@latest" + with: + repo_token: "${{ secrets.GITHUB_TOKEN }}" + automatic_release_tag: "${{ env.RELEASE_VERSION }}" + prerelease: false + title: "${{ env.RELEASE_VERSION }}" + files: build/libs/*.jar + + - name: Publish to Maven + run: ./gradlew publish + env: + MAVEN_USER: ${{ secrets.MAVEN_USER }} + MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..48c525b --- /dev/null +++ b/.gitignore @@ -0,0 +1,32 @@ +.gradle +.settings +/.idea/ +/.vscode/ +/run/ +/build/ +/eclipse/ +.classpath +.project +/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 +src/main/resources/mixins.*.json +*.bat +*.DS_Store +!gradlew.bat diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000..a6b5f68 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,3 @@ +# Any Github changes require admin approval +/.github/** @GTNewHorizons/admin + diff --git a/Mouse Tweaks.iml b/Mouse Tweaks.iml deleted file mode 100644 index 5133546..0000000 --- a/Mouse Tweaks.iml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/ant/build_mousetweaks.xml b/ant/build_mousetweaks.xml deleted file mode 100644 index 99f8ac3..0000000 --- a/ant/build_mousetweaks.xml +++ /dev/null @@ -1,319 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ant/buildnumber.txt b/ant/buildnumber.txt deleted file mode 100644 index 1707364..0000000 --- a/ant/buildnumber.txt +++ /dev/null @@ -1,3 +0,0 @@ -#Build Number for ANT. Do not edit! -#Tue Jul 22 22:11:14 MSK 2014 -build.number=185 diff --git a/ant/litemod.template.json b/ant/litemod.template.json deleted file mode 100644 index b6b4212..0000000 --- a/ant/litemod.template.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "${ant.project.name}", - "mcversion": "${litemodversion}", - "revision": "${build.number}", - "author": "${author}", - "description": "A mod that enhances the inventory management by adding various additional functions to the usual mouse buttons." -} diff --git a/ant/mcmod.template.info b/ant/mcmod.template.info deleted file mode 100644 index 0d314bd..0000000 --- a/ant/mcmod.template.info +++ /dev/null @@ -1,16 +0,0 @@ -[ -{ - "modid": "${modid}", - "name": "${ant.project.name}", - "description": "A mod that enhances the inventory management by adding various additional functions to the usual mouse buttons.", - "version": "${version}", - "mcversion": "${mcversion}", - "url": "http://www.minecraftforum.net/topic/1518185-", - "updateUrl": "", - "authorList": [ "YaLTeR" ], - "credits": "Various open-source mods from where I learned.", - "logoFile": "/mousetweaks_logo.png", - "screenshots": [ ], - "dependencies": [ ] -} -] diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..e182c45 --- /dev/null +++ b/build.gradle @@ -0,0 +1,932 @@ +//version: 1656760175 +/* +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 { + maven { + 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 '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" +} + +if (project.file('.git/HEAD').isFile()) { + apply plugin: 'com.palantir.git-version' +} + +def out = services.get(StyledTextOutputFactory).create('an-output') + +apply plugin: 'forge' + +def projectJavaVersion = JavaLanguageVersion.of(8) + +java { + toolchain { + languageVersion.set(projectJavaVersion) + } +} + +idea { + module { + inheritOutputDirs = true + downloadJavadoc = true + downloadSources = true + } +} + +// Spotless autoformatter +// See https://github.com/diffplug/spotless/tree/main/plugin-gradle +// Can be locally toggled via spotless:off/spotless:on comments +spotless { + encoding 'UTF-8' + + format 'misc', { + target '.gitignore' + + trimTrailingWhitespace() + indentWithSpaces(4) + endWithNewline() + } + java { + toggleOffOn() + importOrder() + removeUnusedImports() + palantirJavaFormat('1.1.0') // last version supporting jvm 8 + } + kotlin { + toggleOffOn() + ktfmt('0.39') + } + groovyGradle { + toggleOffOn() + importOrder() + target '*.gradle' + greclipse('4.19.0') // last version supporting jvm 8 + } +} + +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() +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()) { + 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 = 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 { + maven { + name 'Overmind forge repo mirror' + url 'https://gregtech.overminddl1.com/' + } + if(usesMixins.toBoolean()) { + maven { + name 'sponge' + url 'https://repo.spongepowered.org/repository/maven-public' + } + maven { + url 'https://jitpack.io' + } + } +} + +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') + // 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') + } +} + +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 relocateShadowJar(type: ConfigureShadowRelocation) { + target = tasks.shadowJar + prefix = modGroup + ".shadow" +} + +shadowJar { + project.configurations.shadeCompile.each { dep -> + from(project.zipTree(dep)) { + exclude 'META-INF', 'META-INF/**' + } + } + + manifest { + attributes(getManifestAttributes()) + } + + minimize() // This will only allow shading for actually used classes + configurations = [project.configurations.shadowImplementation, project.configurations.shadowCompile] + dependsOn(relocateShadowJar) +} + +jar { + 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 + + // 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' + } +} + +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 + 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} + 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 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 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) +} diff --git a/dependencies.gradle b/dependencies.gradle new file mode 100644 index 0000000..c773c51 --- /dev/null +++ b/dependencies.gradle @@ -0,0 +1 @@ +dependencies {} diff --git a/forge/forgeSrc.jar b/forge/forgeSrc.jar deleted file mode 100644 index e42fd5f..0000000 Binary files a/forge/forgeSrc.jar and /dev/null differ diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..d32370d --- /dev/null +++ b/gradle.properties @@ -0,0 +1,76 @@ +modName = Mouse Tweaks + +# This is a case-sensitive string to identify your mod. Convention is to use lower case. +modId = MouseTweaks + +modGroup = yalter.mousetweaks + +# 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 = Constants.java +gradleTokenModId = GRADLETOKEN_MODID +gradleTokenModName = GRADLETOKEN_MODNAME +gradleTokenVersion = GRADLETOKEN_VERSION +gradleTokenGroupName = + +# 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 = api + +# 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 = mousetweaks_at.cfg + +# Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled! +usesMixins = false +# Adds some debug arguments like verbose output and export +usesMixinDebug = false +# Specify the location of your implementation of IMixinConfigPlugin. Leave it empty otherwise. +mixinPlugin = +# Specify the package that contains all of your Mixins. You may only place Mixins in this package or the build will fail! +mixinsPackage = +# 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 + +# 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 = diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..5c2d1cf Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..3ab0b72 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +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 diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..83f2acf --- /dev/null +++ b/gradlew @@ -0,0 +1,188 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..9618d8d --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,100 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/jitpack.yml b/jitpack.yml new file mode 100644 index 0000000..09bbb51 --- /dev/null +++ b/jitpack.yml @@ -0,0 +1,2 @@ +before_install: + - ./gradlew setupCIWorkspace \ No newline at end of file diff --git a/repositories.gradle b/repositories.gradle new file mode 100644 index 0000000..0ac475d --- /dev/null +++ b/repositories.gradle @@ -0,0 +1 @@ +repositories {} diff --git a/src/main/java/yalter/mousetweaks/Config.java b/src/main/java/yalter/mousetweaks/Config.java index 32cbec3..453a722 100644 --- a/src/main/java/yalter/mousetweaks/Config.java +++ b/src/main/java/yalter/mousetweaks/Config.java @@ -4,70 +4,66 @@ import java.io.*; import java.util.Properties; public class Config { - private String fileName; - private Properties properties = new Properties(); + private String fileName; + private Properties properties = new Properties(); - public Config(String fileName) { - this.fileName = fileName; - } + public Config(String fileName) { + this.fileName = fileName; + } - public boolean readConfig() { - properties.clear(); + public boolean readConfig() { + properties.clear(); - try { - FileReader configReader = new FileReader(fileName); - properties.load(configReader); - configReader.close(); + try { + FileReader configReader = new FileReader(fileName); + properties.load(configReader); + configReader.close(); - if (properties.size() == 0) - return false; + if (properties.size() == 0) return false; - return true; - } catch (FileNotFoundException ignored) { - } catch (IOException e) { - Constants.LOGGER.error("Failed to read the config file: " + fileName, e); - } + return true; + } catch (FileNotFoundException ignored) { + } catch (IOException e) { + Constants.LOGGER.error("Failed to read the config file: " + fileName, e); + } - return false; - } + return false; + } - public boolean saveConfig() { - try { - File config = new File(fileName); - File parentDir = config.getParentFile(); - if (!parentDir.exists()) - parentDir.mkdirs(); + public boolean saveConfig() { + try { + File config = new File(fileName); + File parentDir = config.getParentFile(); + if (!parentDir.exists()) parentDir.mkdirs(); - FileWriter configWriter = new FileWriter(config); - properties.store(configWriter, null); - configWriter.close(); + FileWriter configWriter = new FileWriter(config); + properties.store(configWriter, null); + configWriter.close(); - return true; - } catch (IOException e) { + return true; + } catch (IOException e) { Constants.LOGGER.error("Failed to write the config file: " + fileName, e); - } + } - return false; - } + return false; + } - public String getOrCreateProperty(String name, String defaultValue) { - if (properties.containsKey(name)) - return properties.getProperty(name); - else - properties.setProperty(name, defaultValue); + public String getOrCreateProperty(String name, String defaultValue) { + if (properties.containsKey(name)) return properties.getProperty(name); + else properties.setProperty(name, defaultValue); - return defaultValue; - } + return defaultValue; + } - public int getOrCreateIntProperty(String name, int defaultValue) { - return Integer.parseInt(getOrCreateProperty(name, String.valueOf(defaultValue))); - } + public int getOrCreateIntProperty(String name, int defaultValue) { + return Integer.parseInt(getOrCreateProperty(name, String.valueOf(defaultValue))); + } - public void setProperty(String name, String value) { - properties.setProperty(name, value); - } + public void setProperty(String name, String value) { + properties.setProperty(name, value); + } - public void setIntProperty(String name, int value) { - setProperty(name, String.valueOf(value)); - } + public void setIntProperty(String name, int value) { + setProperty(name, String.valueOf(value)); + } } diff --git a/src/main/java/yalter/mousetweaks/Constants.java b/src/main/java/yalter/mousetweaks/Constants.java index 4d8bdc4..e5fd981 100644 --- a/src/main/java/yalter/mousetweaks/Constants.java +++ b/src/main/java/yalter/mousetweaks/Constants.java @@ -4,50 +4,22 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class Constants { - public static final String MOD_NAME = "@MODNAME@"; - public static final String MOD_ID = "@MODID@"; - public static final String MOD_VERSION = "@VERSION@"; - + + public static final String MOD_NAME = "GRADLETOKEN_MODNAME"; + public static final String MOD_ID = "GRADLETOKEN_MODID"; + public static final String MOD_VERSION = "GRADLETOKEN_VERSION"; + public static final Logger LOGGER = LogManager.getLogger(MOD_NAME); - // Obfuscated names - public static final String ISMOUSEOVERSLOT_NAME = "a"; - public static final String FIELDE_NAME = "H"; - public static final String FIELDq_NAME = "t"; - public static final String MCPROFILER_NAME = "z"; + // Inventory-related stuff + public static final int INVENTORY_SIZE = 36; // Size of the player inventory - // Forge obfuscated names - public static final String ISMOUSEOVERSLOT_FORGE_NAME = "func_146981_a"; - public static final String FIELDE_FORGE_NAME = "field_146995_H"; - public static final String FIELDq_FORGE_NAME = "field_147007_t"; - public static final String MCPROFILER_FORGE_NAME = "field_71424_I"; - - // MCP names - these are the same as Forge ones for the most part - public static final String ISMOUSEOVERSLOT_MCP_NAME = "isMouseOverSlot"; - public static final String FIELDE_MCP_NAME = "ignoreMouseUp"; - public static final String FIELDq_MCP_NAME = "dragSplitting"; - public static final String MCPROFILER_MCP_NAME = "mcProfiler"; - - // OnTick methods - public static final String ONTICKMETHOD_FORGE_NAME = "Forge"; - public static final String ONTICKMETHOD_LITELOADER_NAME = "LiteLoader"; - public static final String ONTICKMETHOD_PROFILER_NAME = "Minecraft"; - - // Inventory-related stuff - public static final int INVENTORY_SIZE = 36; // Size of the player inventory - - // Mod GUI container IDs - public static final int NOTASSIGNED = -1; // When we haven't determined it yet. - public static final int NOTGUICONTAINER = 0; // This is not a container GUI. - public static final int MINECRAFT = 1; // Containers that should be compatible with vanilla Minecraft ones. - public static final int MTMODGUICONTAINER = 2; // Containers that implement the IMTModGuiContainer interface. - public static final int FORESTRY = 3; // Forestry containers. - public static final int CODECHICKENCORE = 4; // CodeChickenCore containers. - public static final int NEI = 5; // NotEnoughItems containers (like the crafting menu). - - public enum EntryPoint { - UNDEFINED, - FORGE, - LITELOADER - } + // Mod GUI container IDs + public static final int NOTASSIGNED = -1; // When we haven't determined it yet. + public static final int NOTGUICONTAINER = 0; // This is not a container GUI. + public static final int MINECRAFT = 1; // Containers that should be compatible with vanilla Minecraft ones. + public static final int MTMODGUICONTAINER = 2; // Containers that implement the IMTModGuiContainer interface. + public static final int FORESTRY = 3; // Forestry containers. + public static final int CODECHICKENCORE = 4; // CodeChickenCore containers. + public static final int NEI = 5; // NotEnoughItems containers (like the crafting menu). } diff --git a/src/main/java/yalter/mousetweaks/DeobfuscationLayer.java b/src/main/java/yalter/mousetweaks/DeobfuscationLayer.java index 5f38181..b210d40 100644 --- a/src/main/java/yalter/mousetweaks/DeobfuscationLayer.java +++ b/src/main/java/yalter/mousetweaks/DeobfuscationLayer.java @@ -1,5 +1,6 @@ package yalter.mousetweaks; +import java.util.List; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityClientPlayerMP; import net.minecraft.client.gui.GuiScreen; @@ -8,157 +9,150 @@ import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.client.gui.inventory.GuiContainerCreative; import net.minecraft.client.multiplayer.PlayerControllerMP; import net.minecraft.entity.player.InventoryPlayer; -import net.minecraft.inventory.*; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.ContainerFurnace; +import net.minecraft.inventory.ContainerPlayer; +import net.minecraft.inventory.ContainerRepair; +import net.minecraft.inventory.ContainerWorkbench; +import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; import org.lwjgl.input.Mouse; -import java.util.List; - public class DeobfuscationLayer { - protected static Minecraft mc; + protected static Minecraft mc; - protected static GuiScreen getCurrentScreen() { - return mc.currentScreen; - } + protected static GuiScreen getCurrentScreen() { + return mc.currentScreen; + } - protected static boolean isGuiContainer(GuiScreen guiScreen) { - return (guiScreen != null) && (guiScreen instanceof GuiContainer); - } + protected static boolean isGuiContainer(GuiScreen guiScreen) { + return (guiScreen != null) && (guiScreen instanceof GuiContainer); + } - protected static boolean isValidGuiContainer(GuiScreen guiScreen) { - return (guiScreen != null) - && !(guiScreen.getClass().getSimpleName().contains("CJB_GuiCrafting")) - && !(guiScreen.getClass().equals(GuiContainerCreative.class)); - } + protected static boolean isValidGuiContainer(GuiScreen guiScreen) { + return (guiScreen != null) + && !(guiScreen.getClass().getSimpleName().contains("CJB_GuiCrafting")) + && !(guiScreen.getClass().equals(GuiContainerCreative.class)); + } - protected static boolean isVanillaCraftingOutputSlot(Container container, Slot slot) { - return ((container instanceof ContainerWorkbench) && (getSlotNumber(slot) == 0)) - || ((container instanceof ContainerPlayer) && (getSlotNumber(slot) == 0)) - || ((container instanceof ContainerFurnace) && (getSlotNumber(slot) == 2)) - || ((container instanceof ContainerRepair) && (getSlotNumber(slot) == 2)); - } + protected static boolean isVanillaCraftingOutputSlot(Container container, Slot slot) { + return ((container instanceof ContainerWorkbench) && (getSlotNumber(slot) == 0)) + || ((container instanceof ContainerPlayer) && (getSlotNumber(slot) == 0)) + || ((container instanceof ContainerFurnace) && (getSlotNumber(slot) == 2)) + || ((container instanceof ContainerRepair) && (getSlotNumber(slot) == 2)); + } - protected static GuiContainer asGuiContainer(GuiScreen guiScreen) { - return (GuiContainer) guiScreen; - } + protected static GuiContainer asGuiContainer(GuiScreen guiScreen) { + return (GuiContainer) guiScreen; + } - protected static Container asContainer(Object obj) { - return (Container) obj; - } + protected static Container asContainer(Object obj) { + return (Container) obj; + } - protected static Slot asSlot(Object obj) { - return (Slot) obj; - } + protected static Slot asSlot(Object obj) { + return (Slot) obj; + } - protected static Container getContainer(GuiContainer guiContainer) { - return guiContainer.inventorySlots; - } + protected static Container getContainer(GuiContainer guiContainer) { + return guiContainer.inventorySlots; + } - protected static List getSlots(Container container) { - return container.inventorySlots; - } + protected static List getSlots(Container container) { + return container.inventorySlots; + } - protected static Slot getSlot(Container container, int index) { - return (Slot) (getSlots(container).get(index)); - } + protected static Slot getSlot(Container container, int index) { + return (Slot) (getSlots(container).get(index)); + } - protected static ItemStack getSlotStack(Slot slot) { - return (slot == null) ? null : slot.getStack(); - } + protected static ItemStack getSlotStack(Slot slot) { + return (slot == null) ? null : slot.getStack(); + } - protected static int getWindowId(Container container) { - return container.windowId; - } + protected static int getWindowId(Container container) { + return container.windowId; + } - protected static void windowClick(int windowId, int slotNumber, int mouseButton, - int shiftPressed) { - // if (slotNumber != -1) { - getPlayerController().windowClick(windowId, slotNumber, mouseButton, shiftPressed, - getThePlayer()); - // } - } + protected static void windowClick(int windowId, int slotNumber, int mouseButton, int shiftPressed) { + // if (slotNumber != -1) { + getPlayerController().windowClick(windowId, slotNumber, mouseButton, shiftPressed, getThePlayer()); + // } + } - protected static EntityClientPlayerMP getThePlayer() { - return mc.thePlayer; - } + protected static EntityClientPlayerMP getThePlayer() { + return mc.thePlayer; + } - protected static InventoryPlayer getInventoryPlayer() { - return getThePlayer().inventory; - } + protected static InventoryPlayer getInventoryPlayer() { + return getThePlayer().inventory; + } - protected static int getDisplayWidth() { - return mc.displayWidth; - } + protected static int getDisplayWidth() { + return mc.displayWidth; + } - protected static int getDisplayHeight() { - return mc.displayHeight; - } + protected static int getDisplayHeight() { + return mc.displayHeight; + } - protected static ItemStack getStackOnMouse() { - return getInventoryPlayer().getItemStack(); - } + protected static ItemStack getStackOnMouse() { + return getInventoryPlayer().getItemStack(); + } - protected static PlayerControllerMP getPlayerController() { - return mc.playerController; - } + protected static PlayerControllerMP getPlayerController() { + return mc.playerController; + } - protected static int getSlotNumber(Slot slot) { - return slot.slotNumber; - } + protected static int getSlotNumber(Slot slot) { + return slot.slotNumber; + } - protected static int getItemStackSize(ItemStack itemStack) { - return itemStack.stackSize; - } + protected static int getItemStackSize(ItemStack itemStack) { + return itemStack.stackSize; + } - protected static int getMaxItemStackSize(ItemStack itemStack) { - return itemStack.getMaxStackSize(); - } + protected static int getMaxItemStackSize(ItemStack itemStack) { + return itemStack.getMaxStackSize(); + } - protected static ItemStack copyItemStack(ItemStack itemStack) { - return (itemStack == null) ? null : itemStack.copy(); - } + protected static ItemStack copyItemStack(ItemStack itemStack) { + return (itemStack == null) ? null : itemStack.copy(); + } - protected static boolean areStacksCompatible(ItemStack itemStack1, ItemStack itemStack2) { - return ((itemStack1 == null) || (itemStack2 == null)) - || itemStack1.isItemEqual(itemStack2); - } + protected static boolean areStacksCompatible(ItemStack itemStack1, ItemStack itemStack2) { + return ((itemStack1 == null) || (itemStack2 == null)) || itemStack1.isItemEqual(itemStack2); + } - protected static boolean isMouseOverSlot(GuiContainer guiContainer, Slot slot) { - return (Boolean) Reflection.guiContainerClass.invokeMethod(guiContainer, Constants.ISMOUSEOVERSLOT_FORGE_NAME, slot, getRequiredMouseX(), getRequiredMouseY()); - } + protected static Slot getSelectedSlot(GuiContainer guiContainer, Container container, int slotCount) { + for (int i = 0; i < slotCount; i++) { + Slot slot = getSlot(container, i); + if (guiContainer.isMouseOverSlot(slot, getRequiredMouseX(), getRequiredMouseY())) return slot; + } - protected static Slot getSelectedSlot(GuiContainer guiContainer, Container container, int slotCount) { - for (int i = 0; i < slotCount; i++) { - Slot slot = getSlot(container, i); - if (isMouseOverSlot(guiContainer, slot)) - return slot; - } + return null; + } - return null; - } + /** + * Disables the vanilla RMB drag mechanic in the given GuiContainer. If your guiContainer is based on the vanilla GuiContainer, you can use this method to disable the RMB drag. + * + * @param guiContainer The guiContainer to disable RMB drag in. + */ + public static void disableVanillaRMBDrag(GuiContainer guiContainer) { + guiContainer.field_146995_H = true; + guiContainer.field_147007_t = false; + } - /** - * Disables the vanilla RMB drag mechanic in the given GuiContainer. If your guiContainer is based on the vanilla GuiContainer, you can use this method to disable the RMB drag. - * - * @param guiContainer The guiContainer to disable RMB drag in. - */ - public static void disableVanillaRMBDrag(GuiContainer guiContainer) { - Reflection.guiContainerClass.setFieldValue(guiContainer, Constants.FIELDE_FORGE_NAME, true); - Reflection.guiContainerClass.setFieldValue(guiContainer, Constants.FIELDq_FORGE_NAME, false); - } + protected static int getRequiredMouseX() { + ScaledResolution var8 = new ScaledResolution(mc, getDisplayWidth(), getDisplayHeight()); + int var9 = var8.getScaledWidth(); + return (Mouse.getX() * var9) / getDisplayWidth(); + } - protected static int getRequiredMouseX() { - ScaledResolution var8 = new ScaledResolution(mc, getDisplayWidth(), - getDisplayHeight()); - int var9 = var8.getScaledWidth(); - return (Mouse.getX() * var9) / getDisplayWidth(); - } - - protected static int getRequiredMouseY() { - ScaledResolution var8 = new ScaledResolution(mc, getDisplayWidth(), - getDisplayHeight()); - int var10 = var8.getScaledHeight(); - return var10 - ((Mouse.getY() * var10) / getDisplayHeight()) - 1; - } + protected static int getRequiredMouseY() { + ScaledResolution var8 = new ScaledResolution(mc, getDisplayWidth(), getDisplayHeight()); + int var10 = var8.getScaledHeight(); + return var10 - ((Mouse.getY() * var10) / getDisplayHeight()) - 1; + } } diff --git a/src/main/java/yalter/mousetweaks/Logger.java b/src/main/java/yalter/mousetweaks/Logger.java index f3895bf..714ef50 100644 --- a/src/main/java/yalter/mousetweaks/Logger.java +++ b/src/main/java/yalter/mousetweaks/Logger.java @@ -3,8 +3,7 @@ package yalter.mousetweaks; public class Logger { @Deprecated - public static void Log(String textToLog) { - Constants.LOGGER.info(textToLog); - } - + public static void Log(String textToLog) { + Constants.LOGGER.info(textToLog); + } } diff --git a/src/main/java/yalter/mousetweaks/Main.java b/src/main/java/yalter/mousetweaks/Main.java index e7637af..e2a0fc3 100644 --- a/src/main/java/yalter/mousetweaks/Main.java +++ b/src/main/java/yalter/mousetweaks/Main.java @@ -1,5 +1,6 @@ package yalter.mousetweaks; +import java.io.File; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; import net.minecraft.inventory.Slot; @@ -7,616 +8,477 @@ import net.minecraft.item.ItemStack; import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; -import java.io.File; -import java.util.LinkedList; -import java.util.List; - public class Main extends DeobfuscationLayer { - public static boolean liteLoader = false; - public static boolean minecraftForge = false; - public static boolean optifine = false; - - public static boolean useForge = false; - public static boolean useLiteLoader = false; - public static boolean useProfiler = false; - - public static boolean DisableRMBTweak = false; - - public static int RMBTweak = 0; - public static int LMBTweakWithItem = 0; - public static int LMBTweakWithoutItem = 0; - public static int WheelTweak = 0; - public static int WheelSearchOrder = 1; - - public enum OnTickMethod {PROFILER, FORGE, LITELOADER} - public static List onTickMethodOrder = new LinkedList(); - - @Deprecated - public static int Debug = 0; - - public static Config mainConfig; - private static GuiScreen oldGuiScreen = null; - private static Object container = null; - private static Slot oldSelectedSlot = null; - private static Slot firstSlot = null; - private static ItemStack oldStackOnMouse = null; - private static boolean firstSlotClicked = false; - private static boolean shouldClick = true; - private static boolean disableForThisContainer = false; - private static boolean disableWheelForThisContainer = false; - private static int guiContainerID = 0; - - private static boolean readConfig = false; - private static boolean initialised = false; - private static boolean disabled = false; - - public static boolean initialise() { - return initialise(Constants.EntryPoint.UNDEFINED); - } - - public static boolean initialise(Constants.EntryPoint entryPoint) { - Constants.LOGGER.info("A call to initialise, entry point: " + entryPoint.toString() + "."); - - if (disabled) - return false; - - if (initialised) - return true; - - initialised = true; - - if (!Reflection.reflectGuiContainer()) { - disabled = true; - return false; - } - - mc = Minecraft.getMinecraft(); - - mainConfig = new Config(mc.mcDataDir + File.separator + "config" + File.separator + "MouseTweaks.cfg"); - readConfigFile(); - - minecraftForge = Reflection.doesClassExist("net.minecraftforge.client.MinecraftForgeClient"); - if (minecraftForge) { - Constants.LOGGER.info("Minecraft Forge is installed."); - } else { - Constants.LOGGER.info("Minecraft Forge is not installed."); - } - - liteLoader = ((entryPoint == Constants.EntryPoint.LITELOADER) // If we're initialising from LiteModMouseTweaks, the check is not necessary. - || Reflection.doesClassExist("com.mumfrey.liteloader.core.LiteLoader")); - if (liteLoader) { - Constants.LOGGER.info("LiteLoader is installed."); - } else { - Constants.LOGGER.info("LiteLoader is not installed."); - } - - // Find the first suitable OnTick method. - methodLoop: - for (OnTickMethod method : onTickMethodOrder) { - switch (method) { - case FORGE: - if (minecraftForge) { - useForge = true; - Constants.LOGGER.info("Using Forge for the mod operation."); - break methodLoop; - } - break; - - case LITELOADER: - if (liteLoader) { - useLiteLoader = ((entryPoint == Constants.EntryPoint.LITELOADER) - || Reflection.registerLiteModListenerInLiteLoader()); - if (useLiteLoader) { - Constants.LOGGER.info("Using LiteLoader for the mod operation."); - break methodLoop; - } - } - break; - - case PROFILER: - if (Reflection.replaceProfiler()) { - useProfiler = true; - Constants.LOGGER.info("Using the Minecraft profiler for the mod operation."); - - optifine = Reflection.reflectOptifine(); - - break methodLoop; - } - break; - } - } - - if (!useForge && !useLiteLoader && !useProfiler) { - // Nothing worked at all. - disabled = true; - return false; - } - - ModCompatibility.initialize(); - Constants.LOGGER.info("Mouse Tweaks has been initialised."); - - return true; - } - - public static void readConfigFile() { - boolean loadedConfig = mainConfig.readConfig(); - - RMBTweak = mainConfig.getOrCreateIntProperty("RMBTweak", 1); - LMBTweakWithItem = mainConfig.getOrCreateIntProperty("LMBTweakWithItem", 1); - LMBTweakWithoutItem = mainConfig.getOrCreateIntProperty("LMBTweakWithoutItem", 1); - WheelTweak = mainConfig.getOrCreateIntProperty("WheelTweak", 1); - WheelSearchOrder = mainConfig.getOrCreateIntProperty("WheelSearchOrder", 1); - // Debug = mainConfig.getOrCreateIntProperty("Debug", 0); - - // Load the OnTick method order. - String onTickMethodString = mainConfig.getOrCreateProperty("OnTickMethodOrder", - Constants.ONTICKMETHOD_FORGE_NAME + ", " - + Constants.ONTICKMETHOD_LITELOADER_NAME + ", " - + Constants.ONTICKMETHOD_PROFILER_NAME); - - onTickMethodString = onTickMethodString.trim(); - String onTickMethods[] = onTickMethodString.split("[\\s]*,[\\s]*"); - for (String method : onTickMethods) { - if (Constants.ONTICKMETHOD_FORGE_NAME.equalsIgnoreCase(method) && !onTickMethodOrder.contains(OnTickMethod.FORGE)) - onTickMethodOrder.add(OnTickMethod.FORGE); - else if (Constants.ONTICKMETHOD_LITELOADER_NAME.equalsIgnoreCase(method) && !onTickMethodOrder.contains(OnTickMethod.LITELOADER)) - onTickMethodOrder.add(OnTickMethod.LITELOADER); - else if (Constants.ONTICKMETHOD_PROFILER_NAME.equalsIgnoreCase(method) && !onTickMethodOrder.contains(OnTickMethod.PROFILER)) - onTickMethodOrder.add(OnTickMethod.PROFILER); - } - - // Make sure we have one of each. - if (!onTickMethodOrder.contains(OnTickMethod.FORGE)) - onTickMethodOrder.add(OnTickMethod.FORGE); - if (!onTickMethodOrder.contains(OnTickMethod.LITELOADER)) - onTickMethodOrder.add(OnTickMethod.LITELOADER); - if (!onTickMethodOrder.contains(OnTickMethod.PROFILER)) - onTickMethodOrder.add(OnTickMethod.PROFILER); - - boolean savedConfig = saveConfigFile(); - - if (savedConfig && !loadedConfig) - Constants.LOGGER.info("Mouse Tweaks config file was created."); - } - - public static boolean saveConfigFile() { - mainConfig.setIntProperty("RMBTweak", RMBTweak); - mainConfig.setIntProperty("LMBTweakWithItem", LMBTweakWithItem); - mainConfig.setIntProperty("LMBTweakWithoutItem", LMBTweakWithoutItem); - mainConfig.setIntProperty("WheelTweak", WheelTweak); - mainConfig.setIntProperty("WheelSearchOrder", WheelSearchOrder); - // mainConfig.setIntProperty("Debug", Debug); - - String onTickMethodString = ""; - for (OnTickMethod method : onTickMethodOrder) { - if (!onTickMethodString.isEmpty()) - onTickMethodString += ", "; - - switch (method) { - case FORGE: - onTickMethodString += Constants.ONTICKMETHOD_FORGE_NAME; - break; - - case LITELOADER: - onTickMethodString += Constants.ONTICKMETHOD_LITELOADER_NAME; - break; - - case PROFILER: - onTickMethodString += Constants.ONTICKMETHOD_PROFILER_NAME; - break; - } - } - mainConfig.setProperty("OnTickMethodOrder", onTickMethodString); - - return mainConfig.saveConfig(); - } - - public static void onUpdateInGame() { - GuiScreen currentScreen = getCurrentScreen(); - if (currentScreen == null) { - // Reset stuff - oldGuiScreen = null; - container = null; - oldSelectedSlot = null; - firstSlot = null; - oldStackOnMouse = null; - firstSlotClicked = false; - shouldClick = true; - disableForThisContainer = false; - disableWheelForThisContainer = false; - readConfig = true; - - guiContainerID = Constants.NOTASSIGNED; - } else { - if (readConfig) { - readConfig = false; - readConfigFile(); - } - - if (guiContainerID == Constants.NOTASSIGNED) { - guiContainerID = getGuiContainerID(currentScreen); - } - - onUpdateInGui(currentScreen); - } - } - - public static void onUpdateInGui(GuiScreen currentScreen) { - - if (oldGuiScreen != currentScreen) { - oldGuiScreen = currentScreen; - - // If we opened an inventory from another inventory (for example, NEI's options menu). - guiContainerID = getGuiContainerID(currentScreen); - if (guiContainerID == Constants.NOTGUICONTAINER) - return; - - container = getContainerWithID(currentScreen); - disableForThisContainer = isDisabledForThisContainer(currentScreen); - - Constants.LOGGER.debug(new StringBuilder().append("You have just opened a ").append(getGuiContainerNameFromID(currentScreen)).append(" container (").append(currentScreen.getClass().getSimpleName()).append((container == null) ? "" : "; ").append((container == null) ? "" : container.getClass().getSimpleName()).append("), which has ").append(getSlotCountWithID(currentScreen)).append(" slots!").toString()); - - disableWheelForThisContainer = isWheelDisabledForThisContainer(currentScreen); - } - - if (guiContainerID == Constants.NOTGUICONTAINER) - return; - - if ((Main.DisableRMBTweak || (Main.RMBTweak == 0)) && (Main.LMBTweakWithoutItem == 0) && (Main.LMBTweakWithItem == 0) - && (Main.WheelTweak == 0)) - return; - - if (disableForThisContainer) - return; - - int slotCount = getSlotCountWithID(currentScreen); // It's better to have this here, because there are some inventories that change slot count during - // runtime (for example NEI's crafting recipe GUI). - if (slotCount == 0) // If there are no slots, then there is nothing to do. - return; - - int wheel = ((Main.WheelTweak == 1) && !disableWheelForThisContainer) ? Mouse.getDWheel() / 120 : 0; - - if (!Mouse.isButtonDown(1)) { - firstSlotClicked = false; - firstSlot = null; - shouldClick = true; - } - - Slot selectedSlot = getSelectedSlotWithID(currentScreen, slotCount); - - // Copy the stacks, so that they don't change while we do our stuff. - ItemStack stackOnMouse = copyItemStack(getStackOnMouse()); - ItemStack targetStack = copyItemStack(getSlotStack(selectedSlot)); - - // To correctly determine, when and how the default RMB drag needs to be disabled, we need a bunch of conditions... - if (Mouse.isButtonDown(1) && (oldStackOnMouse != stackOnMouse) && (oldStackOnMouse == null)) { - shouldClick = false; - } - - if (oldSelectedSlot != selectedSlot) { - // ...and some more conditions. - if (Mouse.isButtonDown(1) && !firstSlotClicked && (firstSlot == null) && (oldSelectedSlot != null)) { - if (!areStacksCompatible(stackOnMouse, getSlotStack(oldSelectedSlot))) { - shouldClick = false; - } - - firstSlot = oldSelectedSlot; - } - - if (Mouse.isButtonDown(1) && (oldSelectedSlot == null) && !firstSlotClicked && (firstSlot == null)) { - shouldClick = false; - } - - if (selectedSlot == null) { - oldSelectedSlot = selectedSlot; - - if ((firstSlot != null) && !firstSlotClicked) { - firstSlotClicked = true; - disableRMBDragWithID(currentScreen); - firstSlot = null; - } - - return; - } - - Constants.LOGGER.debug(new StringBuilder().append("You have selected a new slot, it's slot number is ").append(getSlotNumber(selectedSlot)).toString()); - - boolean shiftIsDown = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT); - - if (Mouse.isButtonDown(1)) { // Right mouse button - if ((Main.RMBTweak == 1) && !Main.DisableRMBTweak) { - - if ((stackOnMouse != null) && areStacksCompatible(stackOnMouse, targetStack) - && !isCraftingOutputSlot(currentScreen, selectedSlot)) { - if ((firstSlot != null) && !firstSlotClicked) { - firstSlotClicked = true; - disableRMBDragWithID(currentScreen); - firstSlot = null; - } else { - shouldClick = false; - disableRMBDragWithID(currentScreen); - } - - clickSlot(currentScreen, selectedSlot, 1, false); - } - - } - } else if (Mouse.isButtonDown(0)) { // Left mouse button - if (stackOnMouse != null) { - if (Main.LMBTweakWithItem == 1) { - if ((targetStack != null) && areStacksCompatible(stackOnMouse, targetStack)) { - - if (shiftIsDown) { // If shift is down, we just shift-click the slot and the item gets moved into another inventory. - clickSlot(currentScreen, selectedSlot, 0, true); - } else { // If shift is not down, we need to merge the item stack on the mouse with the one in the slot. - if ((getItemStackSize(stackOnMouse) + getItemStackSize(targetStack)) <= getMaxItemStackSize(stackOnMouse)) { - // We need to click on the slot so that our item stack gets merged with it, - // and then click again to return the stack to the mouse. - // However, if the slot is crafting output, then the item is added to the mouse stack - // on the first click and we don't need to click the second time. - clickSlot(currentScreen, selectedSlot, 0, false); - if (!isCraftingOutputSlot(currentScreen, selectedSlot)) - clickSlot(currentScreen, selectedSlot, 0, false); - } - } - } - - } - } else if (Main.LMBTweakWithoutItem == 1) { - if (targetStack != null) { - if (shiftIsDown) { - clickSlot(currentScreen, selectedSlot, 0, true); - } - } - } - } - - oldSelectedSlot = selectedSlot; - } - - if ((wheel != 0) && (selectedSlot != null)) { - int numItemsToMove = Math.abs(wheel); - Constants.LOGGER.debug("numItemsToMove: " + numItemsToMove); - - if (slotCount > Constants.INVENTORY_SIZE) { - ItemStack originalStack = getSlotStack(selectedSlot); - boolean isCraftingOutput = isCraftingOutputSlot(currentScreen, selectedSlot); - - if ((originalStack != null) - && ((stackOnMouse == null) || (isCraftingOutput ? areStacksCompatible(originalStack, stackOnMouse) : !areStacksCompatible(originalStack, stackOnMouse)))) { - do { - Slot applicableSlot = null; - - int slotCounter = 0; - int countUntil = slotCount - - Constants.INVENTORY_SIZE; - if (getSlotNumber(selectedSlot) < countUntil) { - slotCounter = countUntil; - countUntil = slotCount; - } - - if ((wheel < 0) || (Main.WheelSearchOrder == 0)) { - for (int i = slotCounter; i < countUntil; i++) { - Slot sl = getSlotWithID(currentScreen, i); - ItemStack stackSl = getSlotStack(sl); - - if (stackSl == null) { - if ((applicableSlot == null) - && (wheel < 0) - && sl.isItemValid(originalStack) - && !isCraftingOutputSlot(currentScreen, sl)) { - applicableSlot = sl; - } - } else if (areStacksCompatible(originalStack, stackSl)) { - if ((wheel < 0) - && (stackSl.stackSize < stackSl.getMaxStackSize())) { - applicableSlot = sl; - break; - } else if (wheel > 0) { - applicableSlot = sl; - break; - } - } - } - } else { - for (int i = countUntil - 1; i >= slotCounter; i--) { - Slot sl = getSlotWithID(currentScreen, i); - ItemStack stackSl = getSlotStack(sl); - - if (stackSl == null) { - if ((applicableSlot == null) - && (wheel < 0) - && sl.isItemValid(originalStack)) { - applicableSlot = sl; - } - } else if (areStacksCompatible(originalStack, stackSl)) { - if ((wheel < 0) - && (stackSl.stackSize < stackSl.getMaxStackSize())) { - applicableSlot = sl; - break; - } else if (wheel > 0) { - applicableSlot = sl; - break; - } - } - } - } - - if (isCraftingOutput) { - if (wheel < 0) { - boolean mouseWasEmpty = stackOnMouse == null; - - for (int i = 0; i < numItemsToMove; i++) { - clickSlot(currentScreen, selectedSlot, 0, false); - } - - if ((applicableSlot != null) - && mouseWasEmpty) { - clickSlot(currentScreen, applicableSlot, 0, false); - } - } - - break; - } - - if (applicableSlot != null) { - Slot slotTo = (wheel < 0) ? applicableSlot : selectedSlot; - Slot slotFrom = (wheel < 0) ? selectedSlot : applicableSlot; - ItemStack stackTo = (getSlotStack(slotTo) != null) ? copyItemStack(getSlotStack(slotTo)) : null; - ItemStack stackFrom = copyItemStack(getSlotStack(slotFrom)); - - if (wheel < 0) { - numItemsToMove = Math.min(numItemsToMove, getItemStackSize(stackFrom)); - - if ((stackTo != null) - && ((getMaxItemStackSize(stackTo) - getItemStackSize(stackTo)) <= numItemsToMove)) { - clickSlot(currentScreen, slotFrom, 0, false); - clickSlot(currentScreen, slotTo, 0, false); - clickSlot(currentScreen, slotFrom, 0, false); - - numItemsToMove -= getMaxItemStackSize(stackTo) - getItemStackSize(stackTo); - } else { - clickSlot(currentScreen, slotFrom, 0, false); - - if (getItemStackSize(stackFrom) <= numItemsToMove) { - clickSlot(currentScreen, slotTo, 0, false); - } else { - for (int i = 0; i < numItemsToMove; i++) { - clickSlot(currentScreen, slotTo, 1, false); - } - } - - clickSlot(currentScreen, slotFrom, 0, false); - - numItemsToMove = 0; - } - } else { - if ((getMaxItemStackSize(stackTo) - getItemStackSize(stackTo)) <= numItemsToMove) { - clickSlot(currentScreen, slotFrom, 0, false); - clickSlot(currentScreen, slotTo, 0, false); - clickSlot(currentScreen, slotFrom, 0, false); - } else { - clickSlot(currentScreen, slotFrom, 0, false); - - if (getItemStackSize(stackFrom) <= numItemsToMove) { - clickSlot(currentScreen, slotTo, 0, false); - numItemsToMove -= getMaxItemStackSize(stackFrom); - } else { - for (int i = 0; i < numItemsToMove; i++) { - clickSlot(currentScreen, slotTo, 1, false); - } - - numItemsToMove = 0; - } - - clickSlot(currentScreen, slotFrom, 0, false); - } - - if (getMaxItemStackSize(stackTo) == getMaxItemStackSize(stackTo)) { - numItemsToMove = 0; - } - } - } else { - break; - } - } - while (numItemsToMove != 0); - } - } - } - - oldStackOnMouse = stackOnMouse; - } - - public static int getGuiContainerID(GuiScreen currentScreen) { - int containerID = ModCompatibility.getModGuiContainerID(currentScreen); // This first because a lot of mod containers extend the vanilla Minecraft one. - if (containerID == Constants.NOTGUICONTAINER) - return (isGuiContainer(currentScreen) && isValidGuiContainer(currentScreen)) ? Constants.MINECRAFT : Constants.NOTGUICONTAINER; - else - return containerID; - } - - public static Object getContainerWithID(GuiScreen currentScreen) { - if (guiContainerID == Constants.MINECRAFT) - return getContainer(asGuiContainer(currentScreen)); - else - return ModCompatibility.getModContainer(guiContainerID, currentScreen); - } - - public static int getSlotCountWithID(GuiScreen currentScreen) { - if (guiContainerID == Constants.MINECRAFT) - return getSlots(asContainer(container)).size(); - else - return ModCompatibility.getModSlotCount(guiContainerID, currentScreen, container); - } - - public static String getGuiContainerNameFromID(GuiScreen currentScreen) { - switch (guiContainerID) { - case Constants.NOTASSIGNED: - return "Unknown"; - case Constants.NOTGUICONTAINER: - return "Wrong"; - case Constants.MINECRAFT: - return "Vanilla Minecraft"; - - default: - return ModCompatibility.getModNameFromModGuiContainerID(guiContainerID, currentScreen); - } - } - - public static boolean isDisabledForThisContainer(GuiScreen currentScreen) { - if (guiContainerID == Constants.MINECRAFT) - return false; - else - return ModCompatibility.isDisabledForThisModContainer(guiContainerID, currentScreen, container); - } - - public static boolean isWheelDisabledForThisContainer(GuiScreen currentScreen) { - if (guiContainerID == Constants.MINECRAFT) - return false; - else - return ModCompatibility.isWheelDisabledForThisModContainer(guiContainerID, currentScreen); - } - - public static Slot getSelectedSlotWithID(GuiScreen currentScreen, int slotCount) { - if (guiContainerID == Constants.MINECRAFT) - return getSelectedSlot(asGuiContainer(currentScreen), asContainer(container), slotCount); - else - return ModCompatibility.getModSelectedSlot(guiContainerID, currentScreen, container, slotCount); - } - - public static void clickSlot(GuiScreen currentScreen, Slot targetSlot, int mouseButton, boolean shiftPressed) { - if (guiContainerID == Constants.MINECRAFT) { - windowClick(getWindowId(asContainer(container)), getSlotNumber(targetSlot), mouseButton, shiftPressed ? 1 : 0); - } else { - ModCompatibility.modClickSlot(guiContainerID, currentScreen, container, targetSlot, mouseButton, shiftPressed); - } - } - - public static boolean isCraftingOutputSlot(GuiScreen currentScreen, Slot targetSlot) { - if (guiContainerID == Constants.MINECRAFT) - return isVanillaCraftingOutputSlot(asContainer(container), targetSlot); - else - return ModCompatibility.modIsCraftingOutputSlot(guiContainerID, currentScreen, container, targetSlot); - } - - public static Slot getSlotWithID(GuiScreen currentScreen, int slotNumber) { - if (guiContainerID == Constants.MINECRAFT) - return getSlot(asContainer(container), slotNumber); - else - return ModCompatibility.modGetSlot(guiContainerID, currentScreen, container, slotNumber); - } - - public static void disableRMBDragWithID(GuiScreen currentScreen) { - if (guiContainerID == Constants.MINECRAFT) { - disableVanillaRMBDrag(asGuiContainer(currentScreen)); - - if (shouldClick) { - clickSlot(currentScreen, firstSlot, 1, false); - } - } else { - ModCompatibility.disableRMBDragIfRequired(guiContainerID, currentScreen, container, firstSlot, shouldClick); - } - } + public static boolean DisableRMBTweak = false; + + public static int RMBTweak = 0; + public static int LMBTweakWithItem = 0; + public static int LMBTweakWithoutItem = 0; + public static int WheelTweak = 0; + public static int WheelSearchOrder = 1; + + public static Config mainConfig; + private static GuiScreen oldGuiScreen = null; + private static Object container = null; + private static Slot oldSelectedSlot = null; + private static Slot firstSlot = null; + private static ItemStack oldStackOnMouse = null; + private static boolean firstSlotClicked = false; + private static boolean shouldClick = true; + private static boolean disableForThisContainer = false; + private static boolean disableWheelForThisContainer = false; + private static int guiContainerID = 0; + + private static boolean readConfig = false; + + public static void initialise() { + mc = Minecraft.getMinecraft(); + + mainConfig = new Config(mc.mcDataDir + File.separator + "config" + File.separator + "MouseTweaks.cfg"); + readConfigFile(); + + ModCompatibility.initialize(); + Constants.LOGGER.info("Mouse Tweaks has been initialised."); + } + + public static void readConfigFile() { + boolean loadedConfig = mainConfig.readConfig(); + + RMBTweak = mainConfig.getOrCreateIntProperty("RMBTweak", 1); + LMBTweakWithItem = mainConfig.getOrCreateIntProperty("LMBTweakWithItem", 1); + LMBTweakWithoutItem = mainConfig.getOrCreateIntProperty("LMBTweakWithoutItem", 1); + WheelTweak = mainConfig.getOrCreateIntProperty("WheelTweak", 1); + WheelSearchOrder = mainConfig.getOrCreateIntProperty("WheelSearchOrder", 1); + + boolean savedConfig = saveConfigFile(); + + if (savedConfig && !loadedConfig) Constants.LOGGER.info("Mouse Tweaks config file was created."); + } + + public static boolean saveConfigFile() { + mainConfig.setIntProperty("RMBTweak", RMBTweak); + mainConfig.setIntProperty("LMBTweakWithItem", LMBTweakWithItem); + mainConfig.setIntProperty("LMBTweakWithoutItem", LMBTweakWithoutItem); + mainConfig.setIntProperty("WheelTweak", WheelTweak); + mainConfig.setIntProperty("WheelSearchOrder", WheelSearchOrder); + + return mainConfig.saveConfig(); + } + + public static void onUpdateInGame() { + GuiScreen currentScreen = getCurrentScreen(); + if (currentScreen == null) { + // Reset stuff + oldGuiScreen = null; + container = null; + oldSelectedSlot = null; + firstSlot = null; + oldStackOnMouse = null; + firstSlotClicked = false; + shouldClick = true; + disableForThisContainer = false; + disableWheelForThisContainer = false; + readConfig = true; + + guiContainerID = Constants.NOTASSIGNED; + } else { + if (readConfig) { + readConfig = false; + readConfigFile(); + } + + if (guiContainerID == Constants.NOTASSIGNED) { + guiContainerID = getGuiContainerID(currentScreen); + } + + onUpdateInGui(currentScreen); + } + } + + public static void onUpdateInGui(GuiScreen currentScreen) { + + if (oldGuiScreen != currentScreen) { + oldGuiScreen = currentScreen; + + // If we opened an inventory from another inventory (for example, NEI's options menu). + guiContainerID = getGuiContainerID(currentScreen); + if (guiContainerID == Constants.NOTGUICONTAINER) return; + + container = getContainerWithID(currentScreen); + disableForThisContainer = isDisabledForThisContainer(currentScreen); + + Constants.LOGGER.debug(new StringBuilder() + .append("You have just opened a ") + .append(getGuiContainerNameFromID(currentScreen)) + .append(" container (") + .append(currentScreen.getClass().getSimpleName()) + .append((container == null) ? "" : "; ") + .append((container == null) ? "" : container.getClass().getSimpleName()) + .append("), which has ") + .append(getSlotCountWithID(currentScreen)) + .append(" slots!") + .toString()); + + disableWheelForThisContainer = isWheelDisabledForThisContainer(currentScreen); + } + + if (guiContainerID == Constants.NOTGUICONTAINER) return; + + if ((Main.DisableRMBTweak || (Main.RMBTweak == 0)) + && (Main.LMBTweakWithoutItem == 0) + && (Main.LMBTweakWithItem == 0) + && (Main.WheelTweak == 0)) return; + + if (disableForThisContainer) return; + + int slotCount = getSlotCountWithID( + currentScreen); // It's better to have this here, because there are some inventories that change slot + // count during + // runtime (for example NEI's crafting recipe GUI). + if (slotCount == 0) // If there are no slots, then there is nothing to do. + return; + + int wheel = ((Main.WheelTweak == 1) && !disableWheelForThisContainer) ? Mouse.getDWheel() / 120 : 0; + + if (!Mouse.isButtonDown(1)) { + firstSlotClicked = false; + firstSlot = null; + shouldClick = true; + } + + Slot selectedSlot = getSelectedSlotWithID(currentScreen, slotCount); + + // Copy the stacks, so that they don't change while we do our stuff. + ItemStack stackOnMouse = copyItemStack(getStackOnMouse()); + ItemStack targetStack = copyItemStack(getSlotStack(selectedSlot)); + + // To correctly determine, when and how the default RMB drag needs to be disabled, we need a bunch of + // conditions... + if (Mouse.isButtonDown(1) && (oldStackOnMouse != stackOnMouse) && (oldStackOnMouse == null)) { + shouldClick = false; + } + + if (oldSelectedSlot != selectedSlot) { + // ...and some more conditions. + if (Mouse.isButtonDown(1) && !firstSlotClicked && (firstSlot == null) && (oldSelectedSlot != null)) { + if (!areStacksCompatible(stackOnMouse, getSlotStack(oldSelectedSlot))) { + shouldClick = false; + } + + firstSlot = oldSelectedSlot; + } + + if (Mouse.isButtonDown(1) && (oldSelectedSlot == null) && !firstSlotClicked && (firstSlot == null)) { + shouldClick = false; + } + + if (selectedSlot == null) { + oldSelectedSlot = selectedSlot; + + if ((firstSlot != null) && !firstSlotClicked) { + firstSlotClicked = true; + disableRMBDragWithID(currentScreen); + firstSlot = null; + } + + return; + } + + Constants.LOGGER.debug(new StringBuilder() + .append("You have selected a new slot, it's slot number is ") + .append(getSlotNumber(selectedSlot)) + .toString()); + + boolean shiftIsDown = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT); + + if (Mouse.isButtonDown(1)) { // Right mouse button + if ((Main.RMBTweak == 1) && !Main.DisableRMBTweak) { + + if ((stackOnMouse != null) + && areStacksCompatible(stackOnMouse, targetStack) + && !isCraftingOutputSlot(currentScreen, selectedSlot)) { + if ((firstSlot != null) && !firstSlotClicked) { + firstSlotClicked = true; + disableRMBDragWithID(currentScreen); + firstSlot = null; + } else { + shouldClick = false; + disableRMBDragWithID(currentScreen); + } + + clickSlot(currentScreen, selectedSlot, 1, false); + } + } + } else if (Mouse.isButtonDown(0)) { // Left mouse button + if (stackOnMouse != null) { + if (Main.LMBTweakWithItem == 1) { + if ((targetStack != null) && areStacksCompatible(stackOnMouse, targetStack)) { + + if (shiftIsDown) { // If shift is down, we just shift-click the slot and the item gets moved + // into another inventory. + clickSlot(currentScreen, selectedSlot, 0, true); + } else { // If shift is not down, we need to merge the item stack on the mouse with the one + // in the slot. + if ((getItemStackSize(stackOnMouse) + getItemStackSize(targetStack)) + <= getMaxItemStackSize(stackOnMouse)) { + // We need to click on the slot so that our item stack gets merged with it, + // and then click again to return the stack to the mouse. + // However, if the slot is crafting output, then the item is added to the mouse + // stack + // on the first click and we don't need to click the second time. + clickSlot(currentScreen, selectedSlot, 0, false); + if (!isCraftingOutputSlot(currentScreen, selectedSlot)) + clickSlot(currentScreen, selectedSlot, 0, false); + } + } + } + } + } else if (Main.LMBTweakWithoutItem == 1) { + if (targetStack != null) { + if (shiftIsDown) { + clickSlot(currentScreen, selectedSlot, 0, true); + } + } + } + } + + oldSelectedSlot = selectedSlot; + } + + if ((wheel != 0) && (selectedSlot != null)) { + int numItemsToMove = Math.abs(wheel); + Constants.LOGGER.debug("numItemsToMove: " + numItemsToMove); + + if (slotCount > Constants.INVENTORY_SIZE) { + ItemStack originalStack = getSlotStack(selectedSlot); + boolean isCraftingOutput = isCraftingOutputSlot(currentScreen, selectedSlot); + + if ((originalStack != null) + && ((stackOnMouse == null) + || (isCraftingOutput + ? areStacksCompatible(originalStack, stackOnMouse) + : !areStacksCompatible(originalStack, stackOnMouse)))) { + do { + Slot applicableSlot = null; + + int slotCounter = 0; + int countUntil = slotCount - Constants.INVENTORY_SIZE; + if (getSlotNumber(selectedSlot) < countUntil) { + slotCounter = countUntil; + countUntil = slotCount; + } + + if ((wheel < 0) || (Main.WheelSearchOrder == 0)) { + for (int i = slotCounter; i < countUntil; i++) { + Slot sl = getSlotWithID(currentScreen, i); + ItemStack stackSl = getSlotStack(sl); + + if (stackSl == null) { + if ((applicableSlot == null) + && (wheel < 0) + && sl.isItemValid(originalStack) + && !isCraftingOutputSlot(currentScreen, sl)) { + applicableSlot = sl; + } + } else if (areStacksCompatible(originalStack, stackSl)) { + if ((wheel < 0) && (stackSl.stackSize < stackSl.getMaxStackSize())) { + applicableSlot = sl; + break; + } else if (wheel > 0) { + applicableSlot = sl; + break; + } + } + } + } else { + for (int i = countUntil - 1; i >= slotCounter; i--) { + Slot sl = getSlotWithID(currentScreen, i); + ItemStack stackSl = getSlotStack(sl); + + if (stackSl == null) { + if ((applicableSlot == null) && (wheel < 0) && sl.isItemValid(originalStack)) { + applicableSlot = sl; + } + } else if (areStacksCompatible(originalStack, stackSl)) { + if ((wheel < 0) && (stackSl.stackSize < stackSl.getMaxStackSize())) { + applicableSlot = sl; + break; + } else if (wheel > 0) { + applicableSlot = sl; + break; + } + } + } + } + + if (isCraftingOutput) { + if (wheel < 0) { + boolean mouseWasEmpty = stackOnMouse == null; + + for (int i = 0; i < numItemsToMove; i++) { + clickSlot(currentScreen, selectedSlot, 0, false); + } + + if ((applicableSlot != null) && mouseWasEmpty) { + clickSlot(currentScreen, applicableSlot, 0, false); + } + } + + break; + } + + if (applicableSlot != null) { + Slot slotTo = (wheel < 0) ? applicableSlot : selectedSlot; + Slot slotFrom = (wheel < 0) ? selectedSlot : applicableSlot; + ItemStack stackTo = + (getSlotStack(slotTo) != null) ? copyItemStack(getSlotStack(slotTo)) : null; + ItemStack stackFrom = copyItemStack(getSlotStack(slotFrom)); + + if (wheel < 0) { + numItemsToMove = Math.min(numItemsToMove, getItemStackSize(stackFrom)); + + if ((stackTo != null) + && ((getMaxItemStackSize(stackTo) - getItemStackSize(stackTo)) + <= numItemsToMove)) { + clickSlot(currentScreen, slotFrom, 0, false); + clickSlot(currentScreen, slotTo, 0, false); + clickSlot(currentScreen, slotFrom, 0, false); + + numItemsToMove -= getMaxItemStackSize(stackTo) - getItemStackSize(stackTo); + } else { + clickSlot(currentScreen, slotFrom, 0, false); + + if (getItemStackSize(stackFrom) <= numItemsToMove) { + clickSlot(currentScreen, slotTo, 0, false); + } else { + for (int i = 0; i < numItemsToMove; i++) { + clickSlot(currentScreen, slotTo, 1, false); + } + } + + clickSlot(currentScreen, slotFrom, 0, false); + + numItemsToMove = 0; + } + } else { + if ((getMaxItemStackSize(stackTo) - getItemStackSize(stackTo)) <= numItemsToMove) { + clickSlot(currentScreen, slotFrom, 0, false); + clickSlot(currentScreen, slotTo, 0, false); + clickSlot(currentScreen, slotFrom, 0, false); + } else { + clickSlot(currentScreen, slotFrom, 0, false); + + if (getItemStackSize(stackFrom) <= numItemsToMove) { + clickSlot(currentScreen, slotTo, 0, false); + numItemsToMove -= getMaxItemStackSize(stackFrom); + } else { + for (int i = 0; i < numItemsToMove; i++) { + clickSlot(currentScreen, slotTo, 1, false); + } + + numItemsToMove = 0; + } + + clickSlot(currentScreen, slotFrom, 0, false); + } + + if (getMaxItemStackSize(stackTo) == getMaxItemStackSize(stackTo)) { + numItemsToMove = 0; + } + } + } else { + break; + } + } while (numItemsToMove != 0); + } + } + } + + oldStackOnMouse = stackOnMouse; + } + + public static int getGuiContainerID(GuiScreen currentScreen) { + int containerID = ModCompatibility.getModGuiContainerID( + currentScreen); // This first because a lot of mod containers extend the vanilla Minecraft one. + if (containerID == Constants.NOTGUICONTAINER) + return (isGuiContainer(currentScreen) && isValidGuiContainer(currentScreen)) + ? Constants.MINECRAFT + : Constants.NOTGUICONTAINER; + else return containerID; + } + + public static Object getContainerWithID(GuiScreen currentScreen) { + if (guiContainerID == Constants.MINECRAFT) return getContainer(asGuiContainer(currentScreen)); + else return ModCompatibility.getModContainer(guiContainerID, currentScreen); + } + + public static int getSlotCountWithID(GuiScreen currentScreen) { + if (guiContainerID == Constants.MINECRAFT) + return getSlots(asContainer(container)).size(); + else return ModCompatibility.getModSlotCount(guiContainerID, currentScreen, container); + } + + public static String getGuiContainerNameFromID(GuiScreen currentScreen) { + switch (guiContainerID) { + case Constants.NOTASSIGNED: + return "Unknown"; + case Constants.NOTGUICONTAINER: + return "Wrong"; + case Constants.MINECRAFT: + return "Vanilla Minecraft"; + + default: + return ModCompatibility.getModNameFromModGuiContainerID(guiContainerID, currentScreen); + } + } + + public static boolean isDisabledForThisContainer(GuiScreen currentScreen) { + if (guiContainerID == Constants.MINECRAFT) return false; + else return ModCompatibility.isDisabledForThisModContainer(guiContainerID, currentScreen, container); + } + + public static boolean isWheelDisabledForThisContainer(GuiScreen currentScreen) { + if (guiContainerID == Constants.MINECRAFT) return false; + else return ModCompatibility.isWheelDisabledForThisModContainer(guiContainerID, currentScreen); + } + + public static Slot getSelectedSlotWithID(GuiScreen currentScreen, int slotCount) { + if (guiContainerID == Constants.MINECRAFT) + return getSelectedSlot(asGuiContainer(currentScreen), asContainer(container), slotCount); + else return ModCompatibility.getModSelectedSlot(guiContainerID, currentScreen, container, slotCount); + } + + public static void clickSlot(GuiScreen currentScreen, Slot targetSlot, int mouseButton, boolean shiftPressed) { + if (guiContainerID == Constants.MINECRAFT) { + windowClick( + getWindowId(asContainer(container)), getSlotNumber(targetSlot), mouseButton, shiftPressed ? 1 : 0); + } else { + ModCompatibility.modClickSlot( + guiContainerID, currentScreen, container, targetSlot, mouseButton, shiftPressed); + } + } + + public static boolean isCraftingOutputSlot(GuiScreen currentScreen, Slot targetSlot) { + if (guiContainerID == Constants.MINECRAFT) + return isVanillaCraftingOutputSlot(asContainer(container), targetSlot); + else return ModCompatibility.modIsCraftingOutputSlot(guiContainerID, currentScreen, container, targetSlot); + } + + public static Slot getSlotWithID(GuiScreen currentScreen, int slotNumber) { + if (guiContainerID == Constants.MINECRAFT) return getSlot(asContainer(container), slotNumber); + else return ModCompatibility.modGetSlot(guiContainerID, currentScreen, container, slotNumber); + } + + public static void disableRMBDragWithID(GuiScreen currentScreen) { + if (guiContainerID == Constants.MINECRAFT) { + disableVanillaRMBDrag(asGuiContainer(currentScreen)); + + if (shouldClick) { + clickSlot(currentScreen, firstSlot, 1, false); + } + } else { + ModCompatibility.disableRMBDragIfRequired(guiContainerID, currentScreen, container, firstSlot, shouldClick); + } + } } diff --git a/src/main/java/yalter/mousetweaks/ModCompatibility.java b/src/main/java/yalter/mousetweaks/ModCompatibility.java index 941a191..111afe8 100644 --- a/src/main/java/yalter/mousetweaks/ModCompatibility.java +++ b/src/main/java/yalter/mousetweaks/ModCompatibility.java @@ -5,209 +5,221 @@ import net.minecraft.inventory.Slot; import yalter.mousetweaks.api.IMTModGuiContainer; public class ModCompatibility extends DeobfuscationLayer { - private static boolean initialized = false; + private static boolean initialized = false; - private static boolean forestryInstalled = false; - private static boolean codechickencoreInstalled = false; - private static boolean NEIInstalled = false; + private static boolean forestryInstalled = false; + private static boolean codechickencoreInstalled = false; + private static boolean NEIInstalled = false; - public static void initialize() { - if (initialized) - return; + public static void initialize() { + if (initialized) return; - forestryInstalled = Reflection.reflectForestry(); - if (forestryInstalled) { - Constants.LOGGER.info("Successfully reflected Forestry!"); - } + forestryInstalled = Reflection.reflectForestry(); + if (forestryInstalled) { + Constants.LOGGER.info("Successfully reflected Forestry!"); + } - codechickencoreInstalled = Reflection.reflectCodeChickenCore(); - if (codechickencoreInstalled) { - Constants.LOGGER.info("Successfully reflected CodeChickenCore!"); - } + codechickencoreInstalled = Reflection.reflectCodeChickenCore(); + if (codechickencoreInstalled) { + Constants.LOGGER.info("Successfully reflected CodeChickenCore!"); + } - NEIInstalled = Reflection.reflectNEI(); - if (NEIInstalled) { - Constants.LOGGER.info("Successfully reflected NEI!"); - } + NEIInstalled = Reflection.reflectNEI(); + if (NEIInstalled) { + Constants.LOGGER.info("Successfully reflected NEI!"); + } - initialized = true; - } + initialized = true; + } - public static int getModGuiContainerID(GuiScreen guiScreen) { - if (guiScreen instanceof IMTModGuiContainer) - return Constants.MTMODGUICONTAINER; + public static int getModGuiContainerID(GuiScreen guiScreen) { + if (guiScreen instanceof IMTModGuiContainer) return Constants.MTMODGUICONTAINER; - if (forestryInstalled && Reflection.forestry.isInstance("GuiForestry", guiScreen)) - return Constants.FORESTRY; + if (forestryInstalled && Reflection.forestry.isInstance("GuiForestry", guiScreen)) return Constants.FORESTRY; - if (codechickencoreInstalled && Reflection.codechickencore.isInstance("GuiContainerWidget", guiScreen)) - return Constants.CODECHICKENCORE; + if (codechickencoreInstalled && Reflection.codechickencore.isInstance("GuiContainerWidget", guiScreen)) + return Constants.CODECHICKENCORE; - if ((NEIInstalled - && (Reflection.NEI.isInstance("GuiRecipe", guiScreen))) - || Reflection.NEI.isInstance("GuiEnchantmentModifier", guiScreen)) - return Constants.NEI; + if ((NEIInstalled && (Reflection.NEI.isInstance("GuiRecipe", guiScreen))) + || Reflection.NEI.isInstance("GuiEnchantmentModifier", guiScreen)) return Constants.NEI; - return Constants.NOTGUICONTAINER; - } + return Constants.NOTGUICONTAINER; + } - public static String getModNameFromModGuiContainerID(int id, GuiScreen guiScreen) { - switch (id) { - case Constants.MTMODGUICONTAINER: - return ((IMTModGuiContainer) guiScreen).getModName(); + public static String getModNameFromModGuiContainerID(int id, GuiScreen guiScreen) { + switch (id) { + case Constants.MTMODGUICONTAINER: + return ((IMTModGuiContainer) guiScreen).getModName(); - case Constants.FORESTRY: - return "Forestry"; - case Constants.CODECHICKENCORE: - return "CodeChickenCore"; - case Constants.NEI: - return "NotEnoughItems"; + case Constants.FORESTRY: + return "Forestry"; + case Constants.CODECHICKENCORE: + return "CodeChickenCore"; + case Constants.NEI: + return "NotEnoughItems"; - default: - return "Unknown"; - } - } + default: + return "Unknown"; + } + } - public static boolean isWheelDisabledForThisModContainer(int modGuiContainerID, GuiScreen guiScreen) { - switch (modGuiContainerID) { - case Constants.MTMODGUICONTAINER: - return ((IMTModGuiContainer) guiScreen).isWheelTweakDisabled(); + public static boolean isWheelDisabledForThisModContainer(int modGuiContainerID, GuiScreen guiScreen) { + switch (modGuiContainerID) { + case Constants.MTMODGUICONTAINER: + return ((IMTModGuiContainer) guiScreen).isWheelTweakDisabled(); - default: - return false; - } - } + default: + return false; + } + } - public static Slot modGetSlot(int modGuiContainerID, GuiScreen guiScreen, Object modContainer, int slotNumber) { - switch (modGuiContainerID) { - case Constants.MTMODGUICONTAINER: - return asSlot(((IMTModGuiContainer) guiScreen).getModSlot(modContainer, slotNumber)); + public static Slot modGetSlot(int modGuiContainerID, GuiScreen guiScreen, Object modContainer, int slotNumber) { + switch (modGuiContainerID) { + case Constants.MTMODGUICONTAINER: + return asSlot(((IMTModGuiContainer) guiScreen).getModSlot(modContainer, slotNumber)); - case Constants.FORESTRY: - return getSlot(asContainer(modContainer), slotNumber); - case Constants.NEI: - return getSlot(asContainer(modContainer), slotNumber); + case Constants.FORESTRY: + return getSlot(asContainer(modContainer), slotNumber); + case Constants.NEI: + return getSlot(asContainer(modContainer), slotNumber); - default: - return null; - } - } + default: + return null; + } + } - public static boolean modIsCraftingOutputSlot(int modGuiContainerID, GuiScreen guiScreen, Object modContainer, Slot selectedSlot) { - switch (modGuiContainerID) { - case Constants.MTMODGUICONTAINER: - return ((IMTModGuiContainer) guiScreen).isCraftingOutputSlot(modContainer, selectedSlot); + public static boolean modIsCraftingOutputSlot( + int modGuiContainerID, GuiScreen guiScreen, Object modContainer, Slot selectedSlot) { + switch (modGuiContainerID) { + case Constants.MTMODGUICONTAINER: + return ((IMTModGuiContainer) guiScreen).isCraftingOutputSlot(modContainer, selectedSlot); - case Constants.FORESTRY: - return (Reflection.is(modContainer, "ContainerSqueezer") && ((getSlotNumber(selectedSlot) == 9) || (getSlotNumber(selectedSlot) == 11))) - || (Reflection.is(modContainer, "ContainerMoistener") && (getSlotNumber(selectedSlot) == 9)) - || (Reflection.is(modContainer, "ContainerCentrifuge") && ((getSlotNumber(selectedSlot) >= 1) && (getSlotNumber(selectedSlot) <= 9))) - || (Reflection.is(modContainer, "ContainerCarpenter") && (getSlotNumber(selectedSlot) == 21)) - || (Reflection.is(modContainer, "ContainerFabricator") && (getSlotNumber(selectedSlot) == 20)) - || (Reflection.is(modContainer, "ContainerWorktable") && (getSlotNumber(selectedSlot) == 27)); + case Constants.FORESTRY: + return (Reflection.is(modContainer, "ContainerSqueezer") + && ((getSlotNumber(selectedSlot) == 9) || (getSlotNumber(selectedSlot) == 11))) + || (Reflection.is(modContainer, "ContainerMoistener") && (getSlotNumber(selectedSlot) == 9)) + || (Reflection.is(modContainer, "ContainerCentrifuge") + && ((getSlotNumber(selectedSlot) >= 1) && (getSlotNumber(selectedSlot) <= 9))) + || (Reflection.is(modContainer, "ContainerCarpenter") && (getSlotNumber(selectedSlot) == 21)) + || (Reflection.is(modContainer, "ContainerFabricator") && (getSlotNumber(selectedSlot) == 20)) + || (Reflection.is(modContainer, "ContainerWorktable") && (getSlotNumber(selectedSlot) == 27)); - default: - return false; - } - } + default: + return false; + } + } - public static void modClickSlot(int modGuiContainerID, GuiScreen guiScreen, Object modContainer, Slot targetSlot, int mouseButton, boolean shiftPressed) { - switch (modGuiContainerID) { - case Constants.MTMODGUICONTAINER: - ((IMTModGuiContainer) guiScreen).clickModSlot(modContainer, targetSlot, mouseButton, shiftPressed); - return; + public static void modClickSlot( + int modGuiContainerID, + GuiScreen guiScreen, + Object modContainer, + Slot targetSlot, + int mouseButton, + boolean shiftPressed) { + switch (modGuiContainerID) { + case Constants.MTMODGUICONTAINER: + ((IMTModGuiContainer) guiScreen).clickModSlot(modContainer, targetSlot, mouseButton, shiftPressed); + return; - case Constants.FORESTRY: - Reflection.forestry.invokeMethod(guiScreen, "handleMouseClick", targetSlot, 0, mouseButton, shiftPressed ? 1 : 0); - return; + case Constants.FORESTRY: + Reflection.forestry.invokeMethod( + guiScreen, "handleMouseClick", targetSlot, 0, mouseButton, shiftPressed ? 1 : 0); + return; - case Constants.NEI: - windowClick(getWindowId(asContainer(modContainer)), getSlotNumber(targetSlot), mouseButton, shiftPressed ? 1 : 0); - return; + case Constants.NEI: + windowClick( + getWindowId(asContainer(modContainer)), + getSlotNumber(targetSlot), + mouseButton, + shiftPressed ? 1 : 0); + return; - default: - return; - } - } + default: + return; + } + } - public static Slot getModSelectedSlot(int modGuiContainerID, GuiScreen guiScreen, Object modContainer, int slotCount) { - switch (modGuiContainerID) { - case Constants.MTMODGUICONTAINER: - return asSlot(((IMTModGuiContainer) guiScreen).getModSelectedSlot(modContainer, slotCount)); + public static Slot getModSelectedSlot( + int modGuiContainerID, GuiScreen guiScreen, Object modContainer, int slotCount) { + switch (modGuiContainerID) { + case Constants.MTMODGUICONTAINER: + return asSlot(((IMTModGuiContainer) guiScreen).getModSelectedSlot(modContainer, slotCount)); - case Constants.FORESTRY: - return asSlot(Reflection.forestry.invokeMethod(guiScreen, "getSlotAtPosition", getRequiredMouseX(), getRequiredMouseY())); - case Constants.NEI: - return getSelectedSlot(asGuiContainer(guiScreen), asContainer(modContainer), slotCount); + case Constants.FORESTRY: + return asSlot(Reflection.forestry.invokeMethod( + guiScreen, "getSlotAtPosition", getRequiredMouseX(), getRequiredMouseY())); + case Constants.NEI: + return getSelectedSlot(asGuiContainer(guiScreen), asContainer(modContainer), slotCount); - default: - return null; - } - } + default: + return null; + } + } - public static int getModSlotCount(int modGuiContainerID, GuiScreen guiScreen, Object modContainer) { - switch (modGuiContainerID) { - case Constants.MTMODGUICONTAINER: - return ((IMTModGuiContainer) guiScreen).getModSlotCount(modContainer); + public static int getModSlotCount(int modGuiContainerID, GuiScreen guiScreen, Object modContainer) { + switch (modGuiContainerID) { + case Constants.MTMODGUICONTAINER: + return ((IMTModGuiContainer) guiScreen).getModSlotCount(modContainer); - case Constants.FORESTRY: - return getSlots(asContainer(modContainer)).size(); - case Constants.NEI: - return getSlots(asContainer(modContainer)).size(); + case Constants.FORESTRY: + return getSlots(asContainer(modContainer)).size(); + case Constants.NEI: + return getSlots(asContainer(modContainer)).size(); - default: - return 0; - } - } + default: + return 0; + } + } - public static Object getModContainer(int modGuiContainerID, GuiScreen guiScreen) { - switch (modGuiContainerID) { - case Constants.MTMODGUICONTAINER: - return ((IMTModGuiContainer) guiScreen).getModContainer(); + public static Object getModContainer(int modGuiContainerID, GuiScreen guiScreen) { + switch (modGuiContainerID) { + case Constants.MTMODGUICONTAINER: + return ((IMTModGuiContainer) guiScreen).getModContainer(); - case Constants.FORESTRY: - return Reflection.forestry.getFieldValue("inventorySlots", guiScreen); - case Constants.NEI: - return getContainer(asGuiContainer(guiScreen)); + case Constants.FORESTRY: + return Reflection.forestry.getFieldValue("inventorySlots", guiScreen); + case Constants.NEI: + return getContainer(asGuiContainer(guiScreen)); - default: - return null; - } - } + default: + return null; + } + } - public static void disableRMBDragIfRequired(int guiContainerID, GuiScreen guiScreen, Object modContainer, Slot firstSlot, boolean shouldClick) { - switch (guiContainerID) { - case Constants.MTMODGUICONTAINER: - ((IMTModGuiContainer) guiScreen).disableRMBDragIfRequired(modContainer, firstSlot, shouldClick); + public static void disableRMBDragIfRequired( + int guiContainerID, GuiScreen guiScreen, Object modContainer, Slot firstSlot, boolean shouldClick) { + switch (guiContainerID) { + case Constants.MTMODGUICONTAINER: + ((IMTModGuiContainer) guiScreen).disableRMBDragIfRequired(modContainer, firstSlot, shouldClick); - return; + return; - case Constants.NEI: - disableVanillaRMBDrag(asGuiContainer(guiScreen)); + case Constants.NEI: + disableVanillaRMBDrag(asGuiContainer(guiScreen)); - if (shouldClick) { - modClickSlot(guiContainerID, guiScreen, modContainer, firstSlot, 1, false); - } + if (shouldClick) { + modClickSlot(guiContainerID, guiScreen, modContainer, firstSlot, 1, false); + } - return; + return; - default: - return; - } - } + default: + return; + } + } - public static boolean isDisabledForThisModContainer(int guiContainerID, GuiScreen guiScreen, Object container) { - switch (guiContainerID) { - case Constants.MTMODGUICONTAINER: - return ((IMTModGuiContainer) guiScreen).isMouseTweaksDisabled(); + public static boolean isDisabledForThisModContainer(int guiContainerID, GuiScreen guiScreen, Object container) { + switch (guiContainerID) { + case Constants.MTMODGUICONTAINER: + return ((IMTModGuiContainer) guiScreen).isMouseTweaksDisabled(); - case Constants.CODECHICKENCORE: - return true; - case Constants.NEI: - return !Reflection.NEI.isInstance("GuiEnchantmentModifier", guiScreen); + case Constants.CODECHICKENCORE: + return true; + case Constants.NEI: + return !Reflection.NEI.isInstance("GuiEnchantmentModifier", guiScreen); - default: - return false; - } - } + default: + return false; + } + } } diff --git a/src/main/java/yalter/mousetweaks/ProfilerCustom.java b/src/main/java/yalter/mousetweaks/ProfilerCustom.java deleted file mode 100644 index f90f14a..0000000 --- a/src/main/java/yalter/mousetweaks/ProfilerCustom.java +++ /dev/null @@ -1,28 +0,0 @@ -package yalter.mousetweaks; - -import net.minecraft.client.Minecraft; -import net.minecraft.profiler.Profiler; - -public class ProfilerCustom extends Profiler { - private Minecraft minecraft; - - public ProfilerCustom() { - minecraft = Minecraft.getMinecraft(); - } - - @Override - public void startSection(String sectionName) { - // The useProfiler check is redundant here since the OnTick method cannot change in the runtime (at the time of writing this comment). - if (Main.useProfiler && "gameRenderer".equals(sectionName)) { - Main.onUpdateInGame(); - } - - super.startSection(sectionName); - - if (Main.optifine) { - if (!Reflection.gameSettings.setFieldValue(minecraft.gameSettings, "ofProfiler", true)) { - Main.optifine = false; - } - } - } -} diff --git a/src/main/java/yalter/mousetweaks/Reflection.java b/src/main/java/yalter/mousetweaks/Reflection.java index 4489ad8..262cd6d 100644 --- a/src/main/java/yalter/mousetweaks/Reflection.java +++ b/src/main/java/yalter/mousetweaks/Reflection.java @@ -1,374 +1,196 @@ package yalter.mousetweaks; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.inventory.GuiContainer; -import net.minecraft.client.settings.GameSettings; -import net.minecraft.inventory.Slot; - import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import net.minecraft.inventory.Slot; public class Reflection { - public static ReflectionCache guiContainerClass; - public static ReflectionCache liteLoaderClass; - public static ReflectionCache liteModMouseTweaks; - public static ReflectionCache gameSettings; - public static ReflectionCache minecraft; - - public static ReflectionCache forestry; - public static ReflectionCache codechickencore; - public static ReflectionCache NEI; - - public enum Obfuscation {MCP, FORGE, VANILLA} - private static Obfuscation obfuscation; - private static boolean checkObfuscation = true; - - public static boolean reflectGuiContainer() { - guiContainerClass = new ReflectionCache(); - guiContainerClass.storeClass("GuiContainer", GuiContainer.class); - - Method isMouseOverSlot = getMethod(GuiContainer.class, - getObfuscatedName(Constants.ISMOUSEOVERSLOT_MCP_NAME, Constants.ISMOUSEOVERSLOT_FORGE_NAME, Constants.ISMOUSEOVERSLOT_NAME), Slot.class, int.class, - int.class); - - if (isMouseOverSlot == null) { - Constants.LOGGER.error("Failed to get isMouseOverSlot method, quitting"); - return false; - } - - guiContainerClass.storeMethod(Constants.ISMOUSEOVERSLOT_FORGE_NAME, isMouseOverSlot); - - Field field; - field = getField(GuiContainer.class, - getObfuscatedName(Constants.FIELDE_MCP_NAME, Constants.FIELDE_FORGE_NAME, Constants.FIELDE_NAME)); - - if (field == null) { - Constants.LOGGER.error("Failed to retrieve the E field, disabling RMBTweak"); - Main.DisableRMBTweak = true; - } else { - guiContainerClass.storeField(Constants.FIELDE_FORGE_NAME, field); - - field = getField(GuiContainer.class, - getObfuscatedName(Constants.FIELDq_MCP_NAME, Constants.FIELDq_FORGE_NAME, Constants.FIELDq_NAME)); - - if (field == null) { - Constants.LOGGER.error("Failed to retreive the q field, disabling RMBTweak"); - Main.DisableRMBTweak = true; - } else { - guiContainerClass.storeField(Constants.FIELDq_FORGE_NAME, field); - } - } - - return true; - } - - public static boolean registerLiteModListenerInLiteLoader() { - liteLoaderClass = new ReflectionCache(); - - Class lL = getClass("com.mumfrey.liteloader.core.LiteLoader"); - if (lL != null) { - liteLoaderClass.storeClass("LiteLoader", lL); - - liteLoaderClass.available = true; - - Class llEvents = getClass("com.mumfrey.liteloader.core.Events"); - if (llEvents != null) { - liteLoaderClass.storeClass("Events", llEvents); - - Field llEventsField = getField(lL, "events"); - if (llEventsField != null) { - liteLoaderClass.storeField("events", llEventsField); - - Class lM = getClass("com.mumfrey.liteloader.LiteMod"); - if (lM != null) { - liteLoaderClass.storeClass("LiteMod", lM); - - Method addListener = getMethod(llEvents, "addListener", lM); - if (addListener != null) { - liteLoaderClass.storeMethod("addListener", addListener); - - Method getInstance = getMethod(lL, "getInstance"); - if (getInstance != null) { - liteLoaderClass.storeMethod("getInstance", getInstance); - - Object liteLoaderInstance = liteLoaderClass.invokeStaticMethod("LiteLoader", "getInstance"); - if (liteLoaderInstance != null) { - Object llEventsInstance = liteLoaderClass.getFieldValue("events", liteLoaderInstance); - if (llEventsInstance != null) { - Class mouseTweaks = getClass("yalter.mousetweaks.loaders.LiteModMouseTweaks"); - if (mouseTweaks != null) { - liteModMouseTweaks = new ReflectionCache(); - liteModMouseTweaks.storeClass("LiteModMouseTweaks", mouseTweaks); - - Method getLMMTInstance = getMethod(mouseTweaks, "getInstance"); - if (getLMMTInstance != null) { - liteModMouseTweaks.storeMethod("getInstance", getLMMTInstance); - - Object LMMTInstance = liteModMouseTweaks.invokeStaticMethod("LiteModMouseTweaks", "getInstance"); - if (LMMTInstance != null) { - liteLoaderClass.invokeMethod(llEventsInstance, "addListener", LMMTInstance); - - liteLoaderClass.compatible = true; - Constants.LOGGER.info("Registered the LiteModMouseTweaks' listener in LiteLoader."); - - return true; - } else { - Constants.LOGGER.error("Could not get the instance from the getInstance method of LiteModMouseTweaks! Have you modified the class?"); - } - } else { - Constants.LOGGER.error("Could not get the getInstance method from LiteModMouseTweaks! Have you modified the class?"); - } - } else { - Constants.LOGGER.error("Could not get the LiteModMouseTweaks class! Have you deleted it accidentally?"); - } - } - } else { - Constants.LOGGER.error("Failed to retrieve the LiteLoader instance!"); - } - } - } - } - } - } - } - - return false; - } - - public static boolean reflectOptifine() { - gameSettings = new ReflectionCache(); - gameSettings.storeClass("GameSettings", GameSettings.class); - - Field optifineProfilerEnabled = getField(GameSettings.class, "ofProfiler"); - if (optifineProfilerEnabled != null) { - gameSettings.storeField("ofProfiler", optifineProfilerEnabled); - - Constants.LOGGER.info("Optifine is installed."); - return true; - } - - Constants.LOGGER.info("Optifine is not installed."); - return false; - } - - public static boolean replaceProfiler() { - minecraft = new ReflectionCache(); - minecraft.storeClass("Minecraft", Minecraft.class); - - Field profilerField = getFinalField(Minecraft.class, getObfuscatedName(Constants.MCPROFILER_MCP_NAME, Constants.MCPROFILER_FORGE_NAME, Constants.MCPROFILER_NAME)); - if (profilerField != null) { - minecraft.storeField("mcProfiler", profilerField); - return minecraft.setFieldValue(Minecraft.getMinecraft(), "mcProfiler", new ProfilerCustom()); - } - - Constants.LOGGER.error("Failed to get the Minecraft profiler field!"); - return false; - } - - public static boolean reflectForestry() { - forestry = new ReflectionCache(); - - Class guiForestryClass = getClass("forestry.core.gui.GuiForestry"); - if (guiForestryClass != null) { - forestry.storeClass("GuiForestry", guiForestryClass); - forestry.available = true; - - Field inventorySlotsField = getField(guiForestryClass, "inventorySlots"); - if (inventorySlotsField != null) { - forestry.storeField("inventorySlots", inventorySlotsField); - - Method getSlotAtPositionMethod = getMethod(guiForestryClass, "getSlotAtPosition", int.class, int.class); - if (getSlotAtPositionMethod != null) { - forestry.storeMethod("getSlotAtPosition", getSlotAtPositionMethod); - - Method handleMouseClickMethod = getMethod(guiForestryClass, "handleMouseClick", Slot.class, int.class, int.class, int.class); - if (handleMouseClickMethod != null) { - forestry.storeMethod("handleMouseClick", handleMouseClickMethod); - - forestry.compatible = true; - - // Class containerForestryClass = getClass( "forestry.core.gui.ContainerForestry" ); - // if ( containerForestryClass != null ) { - // forestry.storeClass( "ContainerForestry", containerForestryClass ); - // - // Field slotCountField = getField( containerForestryClass, "slotCount" ); - // if ( slotCountField != null ) { - // forestry.storeField( "slotCount", slotCountField ); - // - // forestry.compatible = true; - // } - // } - } - } - } - } - - return forestry.compatible; - } - - public static boolean reflectCodeChickenCore() { - codechickencore = new ReflectionCache(); - - Class guiContainerWidgetClass = getClass("codechicken.core.inventory.GuiContainerWidget"); - if (guiContainerWidgetClass != null) { - codechickencore.storeClass("GuiContainerWidget", guiContainerWidgetClass); - - codechickencore.available = true; - codechickencore.compatible = true; - } - - return codechickencore.compatible; - } - - public static boolean reflectNEI() { - NEI = new ReflectionCache(); - - Class guiRecipeClass = getClass("codechicken.nei.recipe.GuiRecipe"); - if (guiRecipeClass != null) { - NEI.storeClass("GuiRecipe", guiRecipeClass); - NEI.available = true; - - Class guiEnchantmentModifierClass = getClass("codechicken.nei.GuiEnchantmentModifier"); - if (guiEnchantmentModifierClass != null) { - NEI.storeClass("GuiEnchantmentModifier", guiEnchantmentModifierClass); - - NEI.compatible = true; - } - } - - return NEI.compatible; - } - - public static boolean is(Object object, String name) { - return object.getClass().getSimpleName() == name; - } - - public static boolean doesClassExist(String name) { - Class clazz = getClass(name); - return clazz != null; - } - - public static Class getClass(String name) { - try { - return Class.forName(name); - } catch (ClassNotFoundException e) { - ; - } - - return null; - } - - public static Field getField(Class clazz, String name) { - try { - Field field = null; - - try { - field = clazz.getField(name); - } catch (Exception e) { - field = null; - } - - if (field == null) { - field = clazz.getDeclaredField(name); - } - - field.setAccessible(true); - return field; - } catch (Exception e) { - if (name != "ofProfiler") { - Constants.LOGGER.error("Could not retrieve field \"" + name + "\" from class \"" + clazz.getName() + "\"", e); - } - } - - return null; - } - - public static Field getFinalField(Class clazz, String name) { - try { - Field field = null; - - try { - field = clazz.getField(name); - } catch (Exception e) { - field = null; - } - - if (field == null) { - field = clazz.getDeclaredField(name); - } - - Field modifiers = Field.class.getDeclaredField("modifiers"); - modifiers.setAccessible(true); - - modifiers.set(field, field.getModifiers() & ~Modifier.FINAL); - - field.setAccessible(true); - return field; - } catch (Exception e) { - Constants.LOGGER.error("Could not retrieve field \"" + name + "\" from class \"" + clazz.getName() + "\"", e); - } - - return null; - } - - public static Method getMethod(Class clazz, String name, Class... args) { - try { - Method method = null; - - try { - method = clazz.getMethod(name, args); - } catch (Exception e) { - method = null; - } - - if (method == null) { - if ((args != null) & (args.length != 0)) { - method = clazz.getDeclaredMethod(name, args); - } else { - method = clazz.getDeclaredMethod(name, new Class[0]); - } - } - - method.setAccessible(true); - return method; - } catch (Exception e) { - Constants.LOGGER.error("Could not retrieve method \"" + name + "\" from class \"" + clazz.getName() + "\"", e); - } - - return null; - } - - public static String methodToString(Method method) { - return Modifier.toString(method.getModifiers()) + " " + ((method.getReturnType() != null) ? method - .getReturnType().getName() : "void") + " " + method.getName(); - } - - public static String getObfuscatedName(String mcpName, String forgeName, String originalName) { - if (checkObfuscation) { - checkObfuscation(); - } - - if (obfuscation == Obfuscation.MCP) - return mcpName; - else if (obfuscation == Obfuscation.FORGE) - return forgeName; - else - return originalName; - } - - public static void checkObfuscation() { - checkObfuscation = false; - - Constants.LOGGER.info("Obfuscation check, please ignore the following errors (if they come up)."); - - if (getField(Minecraft.class, Constants.MCPROFILER_MCP_NAME) != null) - obfuscation = Obfuscation.MCP; - else if (getField(Minecraft.class, Constants.MCPROFILER_FORGE_NAME) != null) - obfuscation = Obfuscation.FORGE; - else - obfuscation = Obfuscation.VANILLA; - - Constants.LOGGER.info("Obfuscation check completed."); - } + + public static ReflectionCache forestry; + public static ReflectionCache codechickencore; + public static ReflectionCache NEI; + + public static boolean reflectForestry() { + forestry = new ReflectionCache(); + + Class guiForestryClass = getClass("forestry.core.gui.GuiForestry"); + if (guiForestryClass != null) { + forestry.storeClass("GuiForestry", guiForestryClass); + forestry.available = true; + + Field inventorySlotsField = getField(guiForestryClass, "inventorySlots"); + if (inventorySlotsField != null) { + forestry.storeField("inventorySlots", inventorySlotsField); + + Method getSlotAtPositionMethod = getMethod(guiForestryClass, "getSlotAtPosition", int.class, int.class); + if (getSlotAtPositionMethod != null) { + forestry.storeMethod("getSlotAtPosition", getSlotAtPositionMethod); + + Method handleMouseClickMethod = getMethod( + guiForestryClass, "handleMouseClick", Slot.class, int.class, int.class, int.class); + if (handleMouseClickMethod != null) { + forestry.storeMethod("handleMouseClick", handleMouseClickMethod); + + forestry.compatible = true; + + // Class containerForestryClass = getClass( "forestry.core.gui.ContainerForestry" ); + // if ( containerForestryClass != null ) { + // forestry.storeClass( "ContainerForestry", containerForestryClass ); + // + // Field slotCountField = getField( containerForestryClass, "slotCount" ); + // if ( slotCountField != null ) { + // forestry.storeField( "slotCount", slotCountField ); + // + // forestry.compatible = true; + // } + // } + } + } + } + } + + return forestry.compatible; + } + + public static boolean reflectCodeChickenCore() { + codechickencore = new ReflectionCache(); + + Class guiContainerWidgetClass = getClass("codechicken.core.inventory.GuiContainerWidget"); + if (guiContainerWidgetClass != null) { + codechickencore.storeClass("GuiContainerWidget", guiContainerWidgetClass); + + codechickencore.available = true; + codechickencore.compatible = true; + } + + return codechickencore.compatible; + } + + public static boolean reflectNEI() { + NEI = new ReflectionCache(); + + Class guiRecipeClass = getClass("codechicken.nei.recipe.GuiRecipe"); + if (guiRecipeClass != null) { + NEI.storeClass("GuiRecipe", guiRecipeClass); + NEI.available = true; + + Class guiEnchantmentModifierClass = getClass("codechicken.nei.GuiEnchantmentModifier"); + if (guiEnchantmentModifierClass != null) { + NEI.storeClass("GuiEnchantmentModifier", guiEnchantmentModifierClass); + + NEI.compatible = true; + } + } + + return NEI.compatible; + } + + public static boolean is(Object object, String name) { + return object.getClass().getSimpleName() == name; + } + + public static boolean doesClassExist(String name) { + Class clazz = getClass(name); + return clazz != null; + } + + public static Class getClass(String name) { + try { + return Class.forName(name); + } catch (ClassNotFoundException e) { + ; + } + + return null; + } + + public static Field getField(Class clazz, String name) { + try { + Field field = null; + + try { + field = clazz.getField(name); + } catch (Exception e) { + field = null; + } + + if (field == null) { + field = clazz.getDeclaredField(name); + } + + field.setAccessible(true); + return field; + } catch (Exception e) { + if (name != "ofProfiler") { + Constants.LOGGER.error( + "Could not retrieve field \"" + name + "\" from class \"" + clazz.getName() + "\"", e); + } + } + + return null; + } + + public static Field getFinalField(Class clazz, String name) { + try { + Field field = null; + + try { + field = clazz.getField(name); + } catch (Exception e) { + field = null; + } + + if (field == null) { + field = clazz.getDeclaredField(name); + } + + Field modifiers = Field.class.getDeclaredField("modifiers"); + modifiers.setAccessible(true); + + modifiers.set(field, field.getModifiers() & ~Modifier.FINAL); + + field.setAccessible(true); + return field; + } catch (Exception e) { + Constants.LOGGER.error( + "Could not retrieve field \"" + name + "\" from class \"" + clazz.getName() + "\"", e); + } + + return null; + } + + public static Method getMethod(Class clazz, String name, Class... args) { + try { + Method method = null; + + try { + method = clazz.getMethod(name, args); + } catch (Exception e) { + method = null; + } + + if (method == null) { + if ((args != null) & (args.length != 0)) { + method = clazz.getDeclaredMethod(name, args); + } else { + method = clazz.getDeclaredMethod(name, new Class[0]); + } + } + + method.setAccessible(true); + return method; + } catch (Exception e) { + Constants.LOGGER.error( + "Could not retrieve method \"" + name + "\" from class \"" + clazz.getName() + "\"", e); + } + + return null; + } + + public static String methodToString(Method method) { + return Modifier.toString(method.getModifiers()) + " " + + ((method.getReturnType() != null) ? method.getReturnType().getName() : "void") + " " + + method.getName(); + } } diff --git a/src/main/java/yalter/mousetweaks/ReflectionCache.java b/src/main/java/yalter/mousetweaks/ReflectionCache.java index 6f2c3c9..e6401d4 100644 --- a/src/main/java/yalter/mousetweaks/ReflectionCache.java +++ b/src/main/java/yalter/mousetweaks/ReflectionCache.java @@ -5,97 +5,95 @@ import java.lang.reflect.Method; import java.util.HashMap; public class ReflectionCache { - public boolean available = false; - public boolean compatible = false; - public HashMap> classes = new HashMap<>(); - public HashMap methods = new HashMap<>(); - public HashMap fields = new HashMap<>(); + public boolean available = false; + public boolean compatible = false; + public HashMap> classes = new HashMap<>(); + public HashMap methods = new HashMap<>(); + public HashMap fields = new HashMap<>(); - public ReflectionCache() { - } + public ReflectionCache() {} - public Object getFieldValue(String name, Object obj) { - try { - if (fields.containsKey(name)) { - Field field = fields.get(name); - return field.get(obj); - } + public Object getFieldValue(String name, Object obj) { + try { + if (fields.containsKey(name)) { + Field field = fields.get(name); + return field.get(obj); + } - Constants.LOGGER.error("No such field: " + name); - } catch (Exception e) { - e.printStackTrace(); - Constants.LOGGER.error("Failed to get a value of field: " + name); - } + Constants.LOGGER.error("No such field: " + name); + } catch (Exception e) { + e.printStackTrace(); + Constants.LOGGER.error("Failed to get a value of field: " + name); + } - return null; - } + return null; + } - public boolean setFieldValue(Object obj, String name, Object value) { - try { - if (fields.containsKey(name)) { - Field field = fields.get(name); - field.set(obj, value); + public boolean setFieldValue(Object obj, String name, Object value) { + try { + if (fields.containsKey(name)) { + Field field = fields.get(name); + field.set(obj, value); - return true; - } + return true; + } - Constants.LOGGER.error("No such field: " + name); - } catch (Exception e) { - e.printStackTrace(); - Constants.LOGGER.error("Failed to set a value of field: " + name); - } + Constants.LOGGER.error("No such field: " + name); + } catch (Exception e) { + e.printStackTrace(); + Constants.LOGGER.error("Failed to set a value of field: " + name); + } - return false; - } + return false; + } - public Object invokeMethod(Object obj, String name, Object... args) { - try { - if (methods.containsKey(name)) { - Method method = methods.get(name); + public Object invokeMethod(Object obj, String name, Object... args) { + try { + if (methods.containsKey(name)) { + Method method = methods.get(name); - if (args != null) - return method.invoke(obj, args); + if (args != null) return method.invoke(obj, args); - return method.invoke(obj, new Object[0]); - } + return method.invoke(obj, new Object[0]); + } - Constants.LOGGER.error("No such method: " + name); - } catch (Exception e) { - e.printStackTrace(); - Constants.LOGGER.error("Failed to invoke method: " + name); - } + Constants.LOGGER.error("No such method: " + name); + } catch (Exception e) { + e.printStackTrace(); + Constants.LOGGER.error("Failed to invoke method: " + name); + } - return null; - } + return null; + } - public Object invokeStaticMethod(String className, String name, Object... args) { - if (classes.containsKey(className)) { - Class clazz = classes.get(className); + public Object invokeStaticMethod(String className, String name, Object... args) { + if (classes.containsKey(className)) { + Class clazz = classes.get(className); - return invokeMethod(clazz, name, args); - } + return invokeMethod(clazz, name, args); + } - return null; - } + return null; + } - public boolean isInstance(String className, Object obj) { - if (classes.containsKey(className)) { - Class clazz = classes.get(className); - return clazz.isInstance(obj); - } + public boolean isInstance(String className, Object obj) { + if (classes.containsKey(className)) { + Class clazz = classes.get(className); + return clazz.isInstance(obj); + } - return false; - } + return false; + } - public void storeClass(String name, Class clazz) { - classes.put(name, clazz); - } + public void storeClass(String name, Class clazz) { + classes.put(name, clazz); + } - public void storeMethod(String name, Method method) { - methods.put(name, method); - } + public void storeMethod(String name, Method method) { + methods.put(name, method); + } - public void storeField(String name, Field field) { - fields.put(name, field); - } + public void storeField(String name, Field field) { + fields.put(name, field); + } } diff --git a/src/main/java/yalter/mousetweaks/api/IMTModGuiContainer.java b/src/main/java/yalter/mousetweaks/api/IMTModGuiContainer.java index e16fd67..490dc5d 100644 --- a/src/main/java/yalter/mousetweaks/api/IMTModGuiContainer.java +++ b/src/main/java/yalter/mousetweaks/api/IMTModGuiContainer.java @@ -1,92 +1,92 @@ package yalter.mousetweaks.api; public interface IMTModGuiContainer { - /** - * Returns the API version. - * - * @return The API version. Should return 1 for this version. - */ - public int getAPIVersion(); + /** + * Returns the API version. + * + * @return The API version. Should return 1 for this version. + */ + public int getAPIVersion(); - /** - * Returns the mod name to use in log messages. - * - * @return The name of the mod. - */ - public String getModName(); + /** + * Returns the mod name to use in log messages. + * + * @return The name of the mod. + */ + public String getModName(); - /** - * Returns whether or not Mouse Tweaks should be disabled for this GuiContainer. - * - * @return True if Mouse Tweaks should be disabled, false otherwise. - */ - public boolean isMouseTweaksDisabled(); + /** + * Returns whether or not Mouse Tweaks should be disabled for this GuiContainer. + * + * @return True if Mouse Tweaks should be disabled, false otherwise. + */ + public boolean isMouseTweaksDisabled(); - /** - * Returns whether or not wheelTweak should be disabled for this GuiContainer. - * - * @return True if wheelTweak should be disabled, false otherwise. - */ - public boolean isWheelTweakDisabled(); + /** + * Returns whether or not wheelTweak should be disabled for this GuiContainer. + * + * @return True if wheelTweak should be disabled, false otherwise. + */ + public boolean isWheelTweakDisabled(); - /** - * Returns whether or not the given slot is a crafting output slot. - * - * @param modContainer The container of the given slot. - * @param slot The slot to check. - * @return True if the given slot is a crafting output slot, false otherwise. - */ - public boolean isCraftingOutputSlot(Object modContainer, Object slot); + /** + * Returns whether or not the given slot is a crafting output slot. + * + * @param modContainer The container of the given slot. + * @param slot The slot to check. + * @return True if the given slot is a crafting output slot, false otherwise. + */ + public boolean isCraftingOutputSlot(Object modContainer, Object slot); - /** - * Returns the container of this GuiContainer. If multiple containers are used, returns the one that is used at the moment of the method execution. - * - * @return The container that is currently used. - */ - public Object getModContainer(); + /** + * Returns the container of this GuiContainer. If multiple containers are used, returns the one that is used at the moment of the method execution. + * + * @return The container that is currently used. + */ + public Object getModContainer(); - /** - * Returns the number of slots present in the given container (for containers with variable slot number - the number of slots at the moment of the method execution). - * - * @param modContainer The container to retrieve the number of slots from. - * @return The number of slots in the given container. - */ - public int getModSlotCount(Object modContainer); + /** + * Returns the number of slots present in the given container (for containers with variable slot number - the number of slots at the moment of the method execution). + * + * @param modContainer The container to retrieve the number of slots from. + * @return The number of slots in the given container. + */ + public int getModSlotCount(Object modContainer); - /** - * Returns a slot from this container with the given slot number. - * - * @param modContainer The container from which to retrieve the slot. - * @param slotNumber The number of the slot to be retrieved. - * @return The slot from the given container with the given slot number. - */ - public Object getModSlot(Object modContainer, int slotNumber); + /** + * Returns a slot from this container with the given slot number. + * + * @param modContainer The container from which to retrieve the slot. + * @param slotNumber The number of the slot to be retrieved. + * @return The slot from the given container with the given slot number. + */ + public Object getModSlot(Object modContainer, int slotNumber); - /** - * Returns the currently selected slot (the one under the player's mouse cursor) of the given container, which has the given number of slots. - * - * @param modContainer The container to check. - * @param slotCount The number of slots that this container has. - * @return The slot that is currently selected. Null if none are. - */ - public Object getModSelectedSlot(Object modContainer, int slotCount); + /** + * Returns the currently selected slot (the one under the player's mouse cursor) of the given container, which has the given number of slots. + * + * @param modContainer The container to check. + * @param slotCount The number of slots that this container has. + * @return The slot that is currently selected. Null if none are. + */ + public Object getModSelectedSlot(Object modContainer, int slotCount); - /** - * The method that clicks the given slot of the given container with the given mouse button and shift key state. - * - * @param modContainer The container of the given slot. - * @param slot The slot to click. - * @param mouseButton The mouse button. 0 is the left one, 1 is the right one. - * @param shiftPressed True if the shift key is pressed, false otherwise. - */ - public void clickModSlot(Object modContainer, Object slot, int mouseButton, boolean shiftPressed); + /** + * The method that clicks the given slot of the given container with the given mouse button and shift key state. + * + * @param modContainer The container of the given slot. + * @param slot The slot to click. + * @param mouseButton The mouse button. 0 is the left one, 1 is the right one. + * @param shiftPressed True if the shift key is pressed, false otherwise. + */ + public void clickModSlot(Object modContainer, Object slot, int mouseButton, boolean shiftPressed); - /** - * The method that disables the built-in RMB drag mechanic, if required, in this GuiContainer, with the given first slot in the given container to click if shouldClick is set to true (in vanilla circumstances - your RMB dragging mechanic might work differently). - * - * @param modContainer The container of the first slot. - * @param firstSlot The first slot. - * @param shouldClick True, if the first slot is to be clicked. - */ - public void disableRMBDragIfRequired(Object modContainer, Object firstSlot, boolean shouldClick); + /** + * The method that disables the built-in RMB drag mechanic, if required, in this GuiContainer, with the given first slot in the given container to click if shouldClick is set to true (in vanilla circumstances - your RMB dragging mechanic might work differently). + * + * @param modContainer The container of the first slot. + * @param firstSlot The first slot. + * @param shouldClick True, if the first slot is to be clicked. + */ + public void disableRMBDragIfRequired(Object modContainer, Object firstSlot, boolean shouldClick); } diff --git a/src/main/java/yalter/mousetweaks/loaders/LiteModMouseTweaks.java b/src/main/java/yalter/mousetweaks/loaders/LiteModMouseTweaks.java deleted file mode 100644 index 91fc583..0000000 --- a/src/main/java/yalter/mousetweaks/loaders/LiteModMouseTweaks.java +++ /dev/null @@ -1,54 +0,0 @@ -package yalter.mousetweaks.loaders; - -import com.mumfrey.liteloader.RenderListener; -import net.minecraft.client.gui.GuiScreen; -import yalter.mousetweaks.Constants; -import yalter.mousetweaks.Main; - -import java.io.File; - -public class LiteModMouseTweaks implements RenderListener { - private static LiteModMouseTweaks instance; - - public static LiteModMouseTweaks getInstance() { - if (instance == null) - instance = new LiteModMouseTweaks(); - - return instance; - } - - public LiteModMouseTweaks() { } - - @Override - public void init(File file) { - Main.initialise(Constants.EntryPoint.LITELOADER); - } - - @Override - public void onRender() { - if (Main.useLiteLoader) - Main.onUpdateInGame(); - } - - @Override - public String getName() { - return Constants.MOD_NAME; - } - - @Override - public String getVersion() { - return Constants.MOD_VERSION; - } - - @Override - public void onRenderGui(GuiScreen guiScreen) { } - - @Override - public void onRenderWorld() { } - - @Override - public void onSetupCameraTransform() { } - - @Override - public void upgradeSettings(String s, File file, File file2) { } -} diff --git a/src/main/java/yalter/mousetweaks/loaders/MouseTweaksForge.java b/src/main/java/yalter/mousetweaks/loaders/MouseTweaksForge.java index 2eb2999..3b59b0e 100644 --- a/src/main/java/yalter/mousetweaks/loaders/MouseTweaksForge.java +++ b/src/main/java/yalter/mousetweaks/loaders/MouseTweaksForge.java @@ -8,20 +8,21 @@ import cpw.mods.fml.common.gameevent.TickEvent; import yalter.mousetweaks.Constants; import yalter.mousetweaks.Main; -@Mod(modid = Constants.MOD_ID, name = Constants.MOD_NAME, version = Constants.MOD_VERSION, useMetadata = true) +@Mod( + modid = Constants.MOD_ID, + name = Constants.MOD_NAME, + version = Constants.MOD_VERSION, + acceptedMinecraftVersions = "[1.7.10]") public class MouseTweaksForge { - @Mod.EventHandler - public void init(FMLInitializationEvent event) { - Main.initialise(Constants.EntryPoint.FORGE); - if (Main.useForge) - FMLCommonHandler.instance().bus().register(this); - } + @Mod.EventHandler + public void init(FMLInitializationEvent event) { + Main.initialise(); + FMLCommonHandler.instance().bus().register(this); + } - @SubscribeEvent - public void onRenderTick(TickEvent.RenderTickEvent event) { - // The useForge check is redundant here since the OnTick method cannot change in the runtime (at the time of writing this comment). - if (Main.useForge && event.phase == TickEvent.Phase.START) - Main.onUpdateInGame(); - } + @SubscribeEvent + public void onRenderTick(TickEvent.RenderTickEvent event) { + if (event.phase == TickEvent.Phase.START) Main.onUpdateInGame(); + } } diff --git a/src/main/resources/META-INF/mousetweaks_at.cfg b/src/main/resources/META-INF/mousetweaks_at.cfg new file mode 100644 index 0000000..4bc34e9 --- /dev/null +++ b/src/main/resources/META-INF/mousetweaks_at.cfg @@ -0,0 +1,4 @@ +public net.minecraft.client.gui.inventory.GuiContainer field_146995_H +public net.minecraft.client.gui.inventory.GuiContainer field_147007_t + +public net.minecraft.client.gui.inventory.GuiContainer func_146981_a(Lnet/minecraft/inventory/Slot;II)Z #isMouseOverSlot diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info new file mode 100644 index 0000000..f15f772 --- /dev/null +++ b/src/main/resources/mcmod.info @@ -0,0 +1,21 @@ +{ + "modListVersion": 2, + "modList": [{ + "modid": "${modId}", + "name": "${modName}", + "description": "A mod that enhances the inventory management by adding various additional functions to the usual mouse buttons.", + "version": "${modVersion}", + "mcversion": "${minecraftVersion}", + "url": "https://www.curseforge.com/minecraft/mc-mods/mouse-tweaks", + "updateUrl": "", + "authorList": ["YaLTeR"], + "credits": "Various open-source mods from where I learned.", + "logoFile": "mousetweaks_logo.png", + "screenshots": [], + "parent": "", + "requiredMods": [], + "dependencies": [], + "dependants": [], + "useDependencyInformation": true + }] +}