diff --git a/.github/workflows/release-tags.yml b/.github/workflows/release-tags.yml new file mode 100644 index 0000000..96d37f7 --- /dev/null +++ b/.github/workflows/release-tags.yml @@ -0,0 +1,61 @@ +# 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: Set repository owner and name + run: | + echo "REPOSITORY_OWNER=${GITHUB_REPOSITORY%/*}" >> $GITHUB_ENV + echo "REPOSITORY_NAME=${GITHUB_REPOSITORY#*/}" >> $GITHUB_ENV + + - name: Publish package + run: ./gradlew publish + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + ARTIFACT_GROUP_ID: com.github.${{ env.REPOSITORY_OWNER }} + ARTIFACT_ID: "${{ env.REPOSITORY_NAME }}" + ARTIFACT_VERSION: "${{ env.RELEASE_VERSION }}" + REPOSITORY_NAME: "${{ env.REPOSITORY_NAME }}" + REPOSITORY_OWNER: "${{ env.REPOSITORY_OWNER }}" + diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..b237b51 --- /dev/null +++ b/build.gradle @@ -0,0 +1,545 @@ +import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar + +import java.util.concurrent.TimeUnit + +buildscript { + repositories { + maven { + name = "forge" + url = "https://maven.minecraftforge.net" + } + maven { + name = "sonatype" + url = "https://oss.sonatype.org/content/repositories/snapshots/" + } + maven { + name = "jitpack" + url = "https://jitpack.io" + } + } + dependencies { + classpath 'com.github.GT-IMPACT:ForgeGradle:1.2.4' + } +} + +plugins { + id 'idea' + id("org.ajoberstar.grgit") version("3.1.1") + id("com.github.johnrengelman.shadow") version("4.0.4") + id("com.palantir.git-version") version("0.12.3") + id("maven-publish") +} + +apply plugin: 'forge' + +[compileJava, compileTestJava]*.options*.encoding = 'UTF-8' + +def projectJavaVersion = JavaLanguageVersion.of(8) + +java { + toolchain { + languageVersion.set(projectJavaVersion) + } +} + +idea { + module { + inheritOutputDirs = true + downloadJavadoc = true + downloadSources = true + } +} + +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") + + +String javaSourceDir = "src/main/java/" + +String targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") +if ((getFile(targetPackageJava).exists()) == false) { + throw new GradleException("Could not resolve \"modGroup\"! Could not find " + targetPackageJava) +} + +if (apiPackage) { + targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + if ((getFile(targetPackageJava).exists()) == false) { + throw new GradleException("Could not resolve \"apiPackage\"! Could not find " + targetPackageJava + " or ") + } +} + +if (accessTransformersFile) { + String targetFile = "src/main/resources/META-INF/" + accessTransformersFile + if (getFile(targetFile).exists() == false) { + 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("\\.", "/") + if ((getFile(targetPackageJava).exists()) == false) { + throw new GradleException("Could not resolve \"mixinsPackage\"! Could not find " + targetPackageJava) + } + + String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java" + if ((getFile(targetFileJava).exists()) == false) { + throw new GradleException("Could not resolve \"mixinPlugin\"! Could not find " + targetFileJava) + } +} + +if (coreModClass) { + String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java" + if ((getFile(targetFileJava).exists()) == false) { + throw new GradleException("Could not resolve \"coreModClass\"! Could not find " + targetFileJava) + } +} + +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 +'git config core.fileMode false'.execute() +// Pulls version from git tag +try { + version = minecraftVersion + "-" + gitVersion() +} +catch (Exception e) { + throw new IllegalStateException("This mod must be version controlled by Git AND the repository must provide at least one tag!") +} + +group = modGroup +if (project.hasProperty("customArchiveBaseName") && customArchiveBaseName) { + archivesBaseName = customArchiveBaseName +} else { + archivesBaseName = modId +} + +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, versionDetails().lastTag + } + if (gradleTokenGroupName) { + replace gradleTokenGroupName, modGroup + } + } +} + +if (file("addon.gradle").exists()) { + apply from: "addon.gradle" +} + +apply from: 'repositories.gradle' + +configurations { + implementation.extendsFrom(shadowImplementation) + mods + provided + embedded + compile.extendsFrom provided, embedded +} + +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("org.spongepowered:mixin:0.7.11-SNAPSHOT") { + // 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.3.3:dev") + } +} + +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()) { + getFile("/src/main/resources/mixins." + modId.replaceAll("\\|", "") + ".json").text = """{ + "required": true, + "minVersion": "0.7.11", + "package": "${modGroup}.${mixinsPackage}", + "plugin": "${modGroup}.${mixinPlugin}", + "refmap": "${mixingConfigRefMap}", + "target": "@env(DEFAULT)", + "compatibilityLevel": "JAVA_8" +} + +""" + } +} + +task relocateShadowJar(type: ConfigureShadowRelocation) { + target = tasks.shadowJar + prefix = modGroup + ".shadow" +} + +shadowJar { + manifest { + attributes(getManifestAttributes()) + } + + minimize() // This will only allow shading for actually used classes + configurations = [project.configurations.shadowImplementation] + dependsOn(relocateShadowJar) +} + +jar { + 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 { + def arguments = [] + + if (usesMixins.toBoolean()) { + arguments += [ + "--mods=../build/libs/$modId-${version}.jar", + "--tweakClass org.spongepowered.asm.launch.MixinTweaker" + ] + } + + if (developmentEnvironmentUserName) { + arguments += [ + "--username", + developmentEnvironmentUserName + ] + } + + args(arguments) +} + +runServer { + def arguments = [] + + if (usesMixins.toBoolean()) { + arguments += [ + "--mods=../build/libs/$modId-${version}.jar", + "--tweakClass org.spongepowered.asm.launch.MixinTweaker" + ] + } + + args(arguments) +} + +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 version and mcversion + expand "minecraftVersion": project.minecraft.version, + "modVersion": versionDetails().lastTag, + "modId": modId, + "modName": modName + } + + if (usesMixins.toBoolean()) { + from refMap + } + + // copy everything else, thats not the mcmod.info + from(sourceSets.main.resources.srcDirs) { + exclude 'mcmod.info' + } + } + +def getManifestAttributes() { + def manifestAttributes = [:] + if (containsMixinsAndOrCoreModOnly.toBoolean() == false && (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() == false + ] + } + return manifestAttributes +} + +task sourcesJar(type: Jar) { + from(sourceSets.main.allJava) + from(file("$projectDir/LICENSE")) + getArchiveClassifier().set('sources') +} + +task shadowDevJar(type: ShadowJar) { + from sourceSets.main.output + getArchiveClassifier().set("dev") + + manifest { + attributes(getManifestAttributes()) + } + + minimize() // This will only allow shading for actually used classes + configurations = [project.configurations.shadowImplementation] +} + +task relocateShadowDevJar(type: ConfigureShadowRelocation) { + target = tasks.shadowDevJar + prefix = modGroup + ".shadow" +} + +task circularResolverJar(type: Jar) { + dependsOn(relocateShadowDevJar) + dependsOn(shadowDevJar) + enabled = false +} + +task devJar(type: Jar) { + from sourceSets.main.output + getArchiveClassifier().set("dev") + + manifest { + attributes(getManifestAttributes()) + } + + if (usesShadowedDependencies.toBoolean()) { + dependsOn(circularResolverJar) + enabled = false + } +} + +task apiJar(type: Jar) { + from(sourceSets.main.allJava) { + 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 { + archives sourcesJar + archives devJar + if (apiPackage) { + archives apiJar + } +} + +// publishing +publishing { + publications { + maven(MavenPublication) { + artifact source: jar + artifact source: sourcesJar, classifier: "src" + artifact source: devJar, classifier: "dev" + if (apiPackage) { + artifact source: apiJar, classifier: "api" + } + + groupId = System.getenv("ARTIFACT_GROUP_ID") ?: group + artifactId = System.getenv("ARTIFACT_ID") ?: project.name + version = System.getenv("ARTIFACT_VERSION") ?: project.version + } + } + + repositories { + maven { + String owner = System.getenv("REPOSITORY_OWNER") ?: "Unknown" + String repositoryName = System.getenv("REPOSITORY_NAME") ?: "Unknown" + String githubRepositoryUrl = "https://maven.pkg.github.com/$owner/$repositoryName" + name = "GitHubPackages" + url = githubRepositoryUrl + credentials { + username = System.getenv("GITHUB_ACTOR") ?: "NONE" + password = System.getenv("GITHUB_TOKEN") ?: "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 { + println("Build script update available! Run 'gradle updateBuildScript'") + } +} + +static URL availableBuildScriptUrl() { + new URL("https://gtimpact.space/media/gradle/build.gradle") +} + +boolean performBuildScriptUpdate(String projectDir) { + if (isNewBuildScriptVersionAvailable(projectDir)) { + def buildscriptFile = getFile("build.gradle") + availableBuildScriptUrl().withInputStream { i -> buildscriptFile.withOutputStream { it << i } } + 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' +} + +// Helper methods + +def checkPropertyExists(String propertyName) { + if (project.hasProperty(propertyName) == false) { + 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/SinTh0r4s/ExampleMod1.7.10/blob/main/gradle.properties") + } +} + +def getFile(String relativePath) { + return new File(projectDir, relativePath) +} \ No newline at end of file diff --git a/dependencies.gradle b/dependencies.gradle new file mode 100644 index 0000000..0f47fe4 --- /dev/null +++ b/dependencies.gradle @@ -0,0 +1,6 @@ +dependencies { + compile("net.industrial-craft:industrialcraft-2:2.2.828-experimental:dev") + compile("curse.maven:cofh-core-69162:2388751") + compile("curse.maven:applied-energistics-2:2296430") + compile('com.github.GT-IMPACT:GT5.09OFFBEAT:master-SNAPSHOT') +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..f47264d --- /dev/null +++ b/gradle.properties @@ -0,0 +1,64 @@ +modName = Impact | Mixin Module + +# This is a case-sensitive string to identify your mod. Convention is to use lower case. +modId = impact|mixinmodule + +modGroup = space.gtimpact.mixinmodule + +# 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 + +# Select a username for testing your mod with breakpoints. You may leave this empty for a random user name 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 mods 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 = Main.java +gradleTokenModId = GRADLETOKEN_MODID +gradleTokenModName = GRADLETOKEN_MODNAME +gradleTokenVersion = GRADLETOKEN_VERSION +gradleTokenGroupName = GRADLETOKEN_GROUPNAME + +# In case your mod provides an API for other mods to implement you may declare its package here. Otherwise, you can +# leave this property empty. +# Example value: apiPackage = api + modGroup = com.myname.mymodid -> com.myname.mymodid.api +apiPackage = + +# Specify the configuration file for Forge's access transformers here. I must be placed into /src/main/resources/META-INF/ +# Example value: mymodid_at.cfg +accessTransformersFile = + +# Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled! +usesMixins = true +# Specify the location of your implementation of IMixinConfigPlugin. Leave it empty otherwise. +mixinPlugin = mixinplugin.MixinPlugin +# Specify the package that contains all of your Mixins. You may only place Mixins in this package or the build will fail! +mixinsPackage = mixins +# Specify the core mod entry class if you use a core mod. This class must implement IFMLLoadingPlugin! +# This parameter is for legacy compatibility only +# Example value: coreModClass = asm.FMLPlugin + modGroup = com.myname.mymodid -> com.myname.mymodid.asm.FMLPlugin +coreModClass = +# If your project is only a consolidation of mixins or a core mod and does NOT contain a 'normal' mod ( = some class +# that is annotated with @Mod) you want this to be true. When in doubt: leave it on false! +containsMixinsAndOrCoreModOnly = false + +# 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 = diff --git a/repositories.gradle b/repositories.gradle new file mode 100644 index 0000000..bcb2d05 --- /dev/null +++ b/repositories.gradle @@ -0,0 +1,15 @@ +// Add any additional repositories for your dependencies here + +repositories { + maven { + name = "ic2" + url = "https://maven.ic2.player.to/" + metadataSources { + mavenPom() + artifact() + } + } + maven { + url "https://cursemaven.com" + } +} diff --git a/src/main/java/space/gtimpact/mixinmodule/Main.java b/src/main/java/space/gtimpact/mixinmodule/Main.java new file mode 100644 index 0000000..c3d204d --- /dev/null +++ b/src/main/java/space/gtimpact/mixinmodule/Main.java @@ -0,0 +1,12 @@ +package space.gtimpact.mixinmodule; + +import cpw.mods.fml.common.Mod; +import static space.gtimpact.mixinmodule.Main.*; + +@Mod(modid = MODID, version = VERSION, name = MODNAME, acceptedMinecraftVersions = "[1.7.10]") +public class Main { + public static final String MODID = "GRADLETOKEN_MODID"; + public static final String MODNAME = "GRADLETOKEN_MODNAME"; + public static final String VERSION = "GRADLETOKEN_VERSION"; + public static final String GROUPNAME = "GRADLETOKEN_GROUPNAME"; +} \ No newline at end of file diff --git a/src/main/java/space/gtimpact/mixinmodule/mixinplugin/Mixin.java b/src/main/java/space/gtimpact/mixinmodule/mixinplugin/Mixin.java new file mode 100644 index 0000000..edabb03 --- /dev/null +++ b/src/main/java/space/gtimpact/mixinmodule/mixinplugin/Mixin.java @@ -0,0 +1,65 @@ +package space.gtimpact.mixinmodule.mixinplugin; + +import cpw.mods.fml.relauncher.FMLLaunchHandler; + +import java.util.Arrays; +import java.util.List; + +import static space.gtimpact.mixinmodule.mixinplugin.Side.SERVER; +import static space.gtimpact.mixinmodule.mixinplugin.TargetedMod.*; + +public enum Mixin { + + // + // IMPORTANT: Do not make any references to any mod from this file. This file is loaded quite early on and if + // you refer to other mods you load them as well. The consequence is: You can't inject any previously loaded classes! + // Exception: Tags.java, as long as it is used for Strings only! + // + + InvSlotConsumable_Mixin("ic2.InvSlotConsumable_Mixin", IC2, VANILLA), + NanoSaber_Mixin("ic2.NanoSaber_Mixin", IC2), + MiningLaser_Mixin("ic2.MiningLaser_Mixin", IC2), + ToolPainter_Mixin("ic2.ToolPainter_Mixin", IC2), + BlockBase_Mixin("ic2.BlockBase_Mixin", IC2), + ArmorQuantumSuit_Mixin("ic2.ArmorQuantumSuit_Mixin", IC2), + ArmorNanoSuit_Mixin("ic2.ArmorNanoSuit_Mixin", IC2), + ArmorLappack_Mixin("ic2.ArmorLappack_Mixin", IC2), + ArmorJetpackElectric_Mixin("ic2.ArmorJetpackElectric_Mixin", IC2), + ArmorEnergyPack_Mixin("ic2.ArmorEnergyPack_Mixin", IC2), + ArmorAdvBatPack_Mixin("ic2.ArmorAdvBatPack_Mixin", IC2), + ArmorBatPack_Mixin("ic2.ArmorBatPack_Mixin", IC2), + + MovableTileRegistry_Mixin("ae2.MovableTileRegistry_Mixin", AE, GREGTECH, VANILLA), + + ForgeHooksClient_Mixin("vanilla.ForgeHooksClient_Mixin", VANILLA), + BlockHopper_Mixin("vanilla.BlockHopper_Mixin", VANILLA), + + OreDictionaryArbiter_Mixin("cofh.OreDictionaryArbiter_Mixin", COFH, VANILLA), + CoFHCoreUpdate_Mixin_Mixin("cofh.CoFHCoreUpdate_Mixin", COFH, VANILLA), + ; + public final String mixinClass; + public final List targetedMods; + private final Side side; + + Mixin(String mixinClass, Side side, TargetedMod... targetedMods) { + this.mixinClass = mixinClass; + this.targetedMods = Arrays.asList(targetedMods); + this.side = side; + } + + Mixin(String mixinClass, TargetedMod... targetedMods) { + this.mixinClass = mixinClass; + this.targetedMods = Arrays.asList(targetedMods); + this.side = Side.BOTH; + } + + public boolean shouldLoad(List loadedMods) { + return (side == Side.BOTH || side == SERVER && FMLLaunchHandler.side().isServer() || side == Side.CLIENT && FMLLaunchHandler.side().isClient()) && loadedMods.containsAll(targetedMods); + } +} + +enum Side { + BOTH, + CLIENT, + SERVER; +} \ No newline at end of file diff --git a/src/main/java/space/gtimpact/mixinmodule/mixinplugin/MixinPlugin.java b/src/main/java/space/gtimpact/mixinmodule/mixinplugin/MixinPlugin.java new file mode 100644 index 0000000..c7c0181 --- /dev/null +++ b/src/main/java/space/gtimpact/mixinmodule/mixinplugin/MixinPlugin.java @@ -0,0 +1,108 @@ +package space.gtimpact.mixinmodule.mixinplugin; + +import net.minecraft.launchwrapper.Launch; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.spongepowered.asm.lib.tree.ClassNode; +import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; +import org.spongepowered.asm.mixin.extensibility.IMixinInfo; +import ru.timeconqueror.spongemixins.MinecraftURLClassPath; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import static space.gtimpact.mixinmodule.Main.MODID; +import static space.gtimpact.mixinmodule.mixinplugin.TargetedMod.*; +import static java.nio.file.Files.walk; + +public class MixinPlugin implements IMixinConfigPlugin { + + private static final Logger LOG = LogManager.getLogger(MODID + " mixins"); + private static final Path MODS_DIRECTORY_PATH = new File(Launch.minecraftHome, "mods/").toPath(); + + @Override + public void onLoad(String mixinPackage) { + } + + @Override + public String getRefMapperConfig() { + return null; + } + + @Override + public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + return true; + } + + @Override + public void acceptTargets(Set myTargets, Set otherTargets) { + } + + // This method return a List of mixins. Every mixins in this list will be loaded. + @Override + public List getMixins() { + final boolean isDevelopmentEnvironment = (boolean) Launch.blackboard.get("fml.deobfuscatedEnvironment"); + List loadedMods = Arrays.stream(TargetedMod.values()).filter(mod -> mod == VANILLA || (mod.loadInDevelopment && isDevelopmentEnvironment) || loadJarOf(mod)).collect(Collectors.toList()); + for (TargetedMod mod : TargetedMod.values()) { + if(loadedMods.contains(mod)) { + LOG.info("Found " + mod.modName + "! Integrating now..."); + } + else { + LOG.info("Could not find " + mod.modName + "! Skipping integration...."); + } + } + List mixins = new ArrayList<>(); + for (Mixin mixin : Mixin.values()) { + if (mixin.shouldLoad(loadedMods)) { + mixins.add(mixin.mixinClass); + LOG.debug("Loading mixin: " + mixin.mixinClass); + } + } + return mixins; + } + + private boolean loadJarOf(final TargetedMod mod) { + try { + File jar = findJarOf(mod); + if(jar == null) { + LOG.info("Jar not found for " + mod); + return false; + } + LOG.info("Attempting to add " + jar + " to the URL Class Path"); + if(!jar.exists()) { + throw new FileNotFoundException(jar.toString()); + } + MinecraftURLClassPath.addJar(jar); + return true; + } + catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + public static File findJarOf(final TargetedMod mod) { + try { + return walk(MODS_DIRECTORY_PATH).filter(mod::isMatchingJar).map(Path::toFile).findFirst().orElse(null); + } + catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + @Override + public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + } + + @Override + public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + } +} \ No newline at end of file diff --git a/src/main/java/space/gtimpact/mixinmodule/mixinplugin/TargetedMod.java b/src/main/java/space/gtimpact/mixinmodule/mixinplugin/TargetedMod.java new file mode 100644 index 0000000..83b3156 --- /dev/null +++ b/src/main/java/space/gtimpact/mixinmodule/mixinplugin/TargetedMod.java @@ -0,0 +1,49 @@ +package space.gtimpact.mixinmodule.mixinplugin; + +import com.google.common.io.Files; + +import java.nio.file.Path; + +public enum TargetedMod { + + // + // IMPORTANT: Do not make any references to any mod from this file. This file is loaded quite early on and if + // you refer to other mods you load them as well. The consequence is: You can't inject any previously loaded classes! + // Exception: Tags.java, as long as it is used for Strings only! + // + + // Replace with your injected mods here, but always keep VANILLA: + VANILLA("Minecraft", "unused", true), + GREGTECH("GregTech", "gregtech", true), + IC2("IndustrialCraft 2", "industrialcraft", true), + AE("Applied Energistics 2", "appliedenergistics2", true), + COFH("CoFHCore", "CoFHCore", true), + ; + + public final String modName; + public final String jarNamePrefixLowercase; + // Optional dependencies can be omitted in development. Especially skipping GT5U will drastically speed up your game start! + public final boolean loadInDevelopment; + + TargetedMod(String modName, String jarNamePrefix, boolean loadInDevelopment) { + this.modName = modName; + this.jarNamePrefixLowercase = jarNamePrefix.toLowerCase(); + this.loadInDevelopment = loadInDevelopment; + } + + public boolean isMatchingJar(Path path) { + final String pathString = path.toString(); + final String nameLowerCase = Files.getNameWithoutExtension(pathString).toLowerCase(); + final String fileExtension = Files.getFileExtension(pathString); + + return nameLowerCase.startsWith(jarNamePrefixLowercase) && ("jar".equals(fileExtension) || "litemod".equals(fileExtension)); + } + + @Override + public String toString() { + return "TargetedMod{" + + "modName='" + modName + '\'' + + ", jarNamePrefixLowercase='" + jarNamePrefixLowercase + '\'' + + '}'; + } +} \ No newline at end of file diff --git a/src/main/java/space/gtimpact/mixinmodule/mixins/ae2/MovableTileRegistry_Mixin.java b/src/main/java/space/gtimpact/mixinmodule/mixins/ae2/MovableTileRegistry_Mixin.java new file mode 100644 index 0000000..28ba857 --- /dev/null +++ b/src/main/java/space/gtimpact/mixinmodule/mixins/ae2/MovableTileRegistry_Mixin.java @@ -0,0 +1,57 @@ +package space.gtimpact.mixinmodule.mixins.ae2; + +import appeng.api.movable.IMovableHandler; +import appeng.api.movable.IMovableTile; +import appeng.core.features.registries.MovableTileRegistry; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import net.minecraft.tileentity.TileEntity; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.HashMap; + +@Mixin(MovableTileRegistry.class) +public class MovableTileRegistry_Mixin { + + @Final + @Shadow(remap = false) + private IMovableHandler nullHandler; + + @Final + @Shadow(remap = false) + private HashMap, IMovableHandler> Valid; + + @Inject(method = "askToMove", at = @At("HEAD"), remap = false, cancellable = true) + public void askToMove(TileEntity te, CallbackInfoReturnable cir) { + + Class myClass = te.getClass(); + IMovableHandler canMove = this.Valid.get(myClass); + if (canMove == null) { + canMove = this.testClass(myClass, te); + } + + if (canMove != this.nullHandler) { + if (te instanceof IMovableTile) { + ((IMovableTile)te).prepareToMove(); + } + + te.invalidate(); + cir.setReturnValue(true); + } else { + if (te instanceof IGregTechTileEntity) { + te.invalidate(); + cir.setReturnValue(true); + } + cir.setReturnValue(false); + } + } + + @Shadow(remap = false) + private IMovableHandler testClass(Class myClass, TileEntity te) { + throw new IllegalStateException("Mixin failed to shadow testClass()"); + } +} \ No newline at end of file diff --git a/src/main/java/space/gtimpact/mixinmodule/mixins/cofh/CoFHCoreUpdate_Mixin.java b/src/main/java/space/gtimpact/mixinmodule/mixins/cofh/CoFHCoreUpdate_Mixin.java new file mode 100644 index 0000000..6cb8963 --- /dev/null +++ b/src/main/java/space/gtimpact/mixinmodule/mixins/cofh/CoFHCoreUpdate_Mixin.java @@ -0,0 +1,17 @@ +package space.gtimpact.mixinmodule.mixins.cofh; + +import cofh.mod.updater.UpdateCheckThread; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; + +@Mixin(UpdateCheckThread.class) +public class CoFHCoreUpdate_Mixin { + /** + * @author mitchej123 + * @reason Update URL is long since gone + */ + @Overwrite(remap = false) + public void run() { + // Do nothing + } +} \ No newline at end of file diff --git a/src/main/java/space/gtimpact/mixinmodule/mixins/cofh/OreDictionaryArbiter_Mixin.java b/src/main/java/space/gtimpact/mixinmodule/mixins/cofh/OreDictionaryArbiter_Mixin.java new file mode 100644 index 0000000..0e2d184 --- /dev/null +++ b/src/main/java/space/gtimpact/mixinmodule/mixins/cofh/OreDictionaryArbiter_Mixin.java @@ -0,0 +1,17 @@ +package space.gtimpact.mixinmodule.mixins.cofh; + +import cofh.core.util.oredict.OreDictionaryArbiter; +import cpw.mods.fml.common.FMLCommonHandler; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(OreDictionaryArbiter.class) +public class OreDictionaryArbiter_Mixin { + + @Inject(method = "initialize", at = @At("HEAD"), remap = false, cancellable = true) + private static void initialize(CallbackInfo ci) { + ci.cancel(); + } +} \ No newline at end of file diff --git a/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/ArmorAdvBatPack_Mixin.java b/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/ArmorAdvBatPack_Mixin.java new file mode 100644 index 0000000..e667ddf --- /dev/null +++ b/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/ArmorAdvBatPack_Mixin.java @@ -0,0 +1,19 @@ +package space.gtimpact.mixinmodule.mixins.ic2; + +import ic2.core.item.armor.ItemArmorAdvBatpack; +import ic2.core.item.armor.ItemArmorElectric; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(ItemArmorAdvBatpack.class) +public abstract class ArmorAdvBatPack_Mixin extends ItemArmorElectric { + + public ArmorAdvBatPack_Mixin() { + super(null, null, 0, 0, 0, 0); + } + + @Override + public double getMaxCharge(ItemStack itemStack) { + return 600000D; + } +} \ No newline at end of file diff --git a/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/ArmorBatPack_Mixin.java b/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/ArmorBatPack_Mixin.java new file mode 100644 index 0000000..982400a --- /dev/null +++ b/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/ArmorBatPack_Mixin.java @@ -0,0 +1,19 @@ +package space.gtimpact.mixinmodule.mixins.ic2; + +import ic2.core.item.armor.ItemArmorBatpack; +import ic2.core.item.armor.ItemArmorElectric; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(ItemArmorBatpack.class) +public abstract class ArmorBatPack_Mixin extends ItemArmorElectric { + + public ArmorBatPack_Mixin() { + super(null, null, 0, 0, 0, 0); + } + + @Override + public double getMaxCharge(ItemStack itemStack) { + return 60000D; + } +} \ No newline at end of file diff --git a/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/ArmorEnergyPack_Mixin.java b/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/ArmorEnergyPack_Mixin.java new file mode 100644 index 0000000..6eb26c8 --- /dev/null +++ b/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/ArmorEnergyPack_Mixin.java @@ -0,0 +1,19 @@ +package space.gtimpact.mixinmodule.mixins.ic2; + +import ic2.core.item.armor.ItemArmorElectric; +import ic2.core.item.armor.ItemArmorEnergypack; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(ItemArmorEnergypack.class) +public abstract class ArmorEnergyPack_Mixin extends ItemArmorElectric { + + public ArmorEnergyPack_Mixin() { + super(null, null, 0, 0, 0, 0); + } + + @Override + public double getMaxCharge(ItemStack itemStack) { + return 1E7D; + } +} \ No newline at end of file diff --git a/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/ArmorJetpackElectric_Mixin.java b/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/ArmorJetpackElectric_Mixin.java new file mode 100644 index 0000000..e46cf32 --- /dev/null +++ b/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/ArmorJetpackElectric_Mixin.java @@ -0,0 +1,20 @@ +package space.gtimpact.mixinmodule.mixins.ic2; + +import ic2.api.item.IElectricItem; +import ic2.core.item.armor.ItemArmorJetpackElectric; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(ItemArmorJetpackElectric.class) +public abstract class ArmorJetpackElectric_Mixin implements IElectricItem { + + @Override + public double getMaxCharge(final ItemStack itemStack) { + return 60000D; + } + + @Override + public double getTransferLimit(final ItemStack itemStack) { + return 30; + } +} \ No newline at end of file diff --git a/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/ArmorLappack_Mixin.java b/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/ArmorLappack_Mixin.java new file mode 100644 index 0000000..b4d94ed --- /dev/null +++ b/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/ArmorLappack_Mixin.java @@ -0,0 +1,19 @@ +package space.gtimpact.mixinmodule.mixins.ic2; + +import ic2.core.item.armor.ItemArmorElectric; +import ic2.core.item.armor.ItemArmorLappack; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(ItemArmorLappack.class) +public abstract class ArmorLappack_Mixin extends ItemArmorElectric { + + public ArmorLappack_Mixin() { + super(null, null, 0, 0, 0, 0); + } + + @Override + public double getMaxCharge(ItemStack itemStack) { + return 2.0E7D; + } +} \ No newline at end of file diff --git a/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/ArmorNanoSuit_Mixin.java b/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/ArmorNanoSuit_Mixin.java new file mode 100644 index 0000000..7297160 --- /dev/null +++ b/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/ArmorNanoSuit_Mixin.java @@ -0,0 +1,240 @@ +package space.gtimpact.mixinmodule.mixins.ic2; + +import ic2.api.item.ElectricItem; +import ic2.core.IC2; +import ic2.core.IC2Potion; +import ic2.core.Ic2Items; +import ic2.core.init.MainConfig; +import ic2.core.item.armor.ItemArmorElectric; +import ic2.core.item.armor.ItemArmorNanoSuit; +import ic2.core.util.ConfigUtil; +import ic2.core.util.StackUtil; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.potion.Potion; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.DamageSource; +import net.minecraft.world.World; +import net.minecraftforge.common.ISpecialArmor; +import net.minecraftforge.event.entity.living.LivingFallEvent; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; + +@Mixin(ItemArmorNanoSuit.class) +public abstract class ArmorNanoSuit_Mixin extends ItemArmorElectric { + + private static final Map potionRemovalCost = new HashMap<>(); + + static { + potionRemovalCost.put(Potion.poison.id, 10000); + potionRemovalCost.put(IC2Potion.radiation.id, 10000); + potionRemovalCost.put(Potion.wither.id, 25000); + } + ; + + private float jumpCharge; + + public ArmorNanoSuit_Mixin() { + super(null, null, 0, 0, 0, 0); + } + + @Override + public double getMaxCharge(ItemStack itemStack) { + return 5E6D; + } + + @Override + public ISpecialArmor.ArmorProperties getProperties(final EntityLivingBase player, final ItemStack armor, final DamageSource source, final double damage, final int slot) { + if (source == DamageSource.fall && this.armorType == 3) { + final int energyPerDamage = player.worldObj.provider.dimensionId == 0 ? this.getEnergyPerDamage() : 100; + int damageLimit = Integer.MAX_VALUE; + if (energyPerDamage > 0) { + damageLimit = (int) Math.min(damageLimit, 25.0 * ElectricItem.manager.getCharge(armor) / energyPerDamage); + } + return new ISpecialArmor.ArmorProperties(10, (damage < 8.0) ? 1.0 : 0.875, damageLimit); + } + return super.getProperties(player, armor, source, damage, slot); + } + + @Inject(method = "onEntityLivingFallEvent", at = @At("HEAD"), remap = false, cancellable = true) + public void onEntityLivingFallEvent(LivingFallEvent event, CallbackInfo ci) { + if (IC2.platform.isSimulating() && event.entity instanceof EntityLivingBase) { + final EntityLivingBase entity = (EntityLivingBase) event.entity; + final ItemStack armor = entity.getEquipmentInSlot(1); + if (armor != null && armor.getItem() == this) { + final int fallDamage = (int) event.distance - 3; + if (fallDamage >= 8) { + ci.cancel(); + } + final double energyCost = entity.worldObj.provider.dimensionId == 0 ? this.getEnergyPerDamage() * fallDamage : 100 * fallDamage; + if (energyCost <= ElectricItem.manager.getCharge(armor)) { + ElectricItem.manager.discharge(armor, energyCost, Integer.MAX_VALUE, true, false, false); + event.setCanceled(true); + } + } + } + ci.cancel(); + } + + @Override + public void onArmorTick(final World world, final EntityPlayer player, final ItemStack itemStack) { + final NBTTagCompound nbtData = StackUtil.getOrCreateNbtData(itemStack); + byte toggleTimer = nbtData.getByte("toggleTimer"); + boolean ret = false; + switch (this.armorType) { + case 0: { + IC2.platform.profilerStartSection("NanoHelmet"); + if (player.getAir() <= 100 && player.inventory.hasItemStack(Ic2Items.airCell)) { + StackUtil.consumeInventoryItem(player, Ic2Items.airCell); + player.inventory.addItemStackToInventory(new ItemStack(Ic2Items.cell.getItem())); + player.setAir(player.getAir() + 150); + ret = true; + } + boolean Nightvision = nbtData.getBoolean("Nightvision"); + short hubmode = nbtData.getShort("HudMode"); + if (IC2.keyboard.isAltKeyDown(player) && IC2.keyboard.isModeSwitchKeyDown(player) && toggleTimer == 0) { + toggleTimer = 10; + Nightvision = !Nightvision; + if (IC2.platform.isSimulating()) { + nbtData.setBoolean("Nightvision", Nightvision); + if (Nightvision) { + IC2.platform.messagePlayer(player, "Nightvision enabled."); + } else { + IC2.platform.messagePlayer(player, "Nightvision disabled."); + } + } + } + if (IC2.keyboard.isAltKeyDown(player) && IC2.keyboard.isHudModeKeyDown(player) && toggleTimer == 0) { + toggleTimer = 10; + if (hubmode == 2) { + hubmode = 0; + } else { + ++hubmode; + } + if (IC2.platform.isSimulating()) { + nbtData.setShort("HudMode", hubmode); + switch (hubmode) { + case 0: { + IC2.platform.messagePlayer(player, "HUD disabled."); + break; + } + case 1: { + IC2.platform.messagePlayer(player, "HUD (basic) enabled."); + break; + } + case 2: { + IC2.platform.messagePlayer(player, "HUD (extended) enabled"); + break; + } + } + } + } + if (IC2.platform.isSimulating() && toggleTimer > 0) { + --toggleTimer; + nbtData.setByte("toggleTimer", toggleTimer); + } + if (Nightvision && IC2.platform.isSimulating() && ElectricItem.manager.use(itemStack, 1.0, player)) { + final int skylight = 1; + if (skylight > 8) { + IC2.platform.removePotion(player, Potion.nightVision.id); + player.addPotionEffect(new PotionEffect(Potion.blindness.id, 100, 0, true)); + } else { + IC2.platform.removePotion(player, Potion.blindness.id); + player.addPotionEffect(new PotionEffect(Potion.nightVision.id, 300, 0, true)); + } + ret = true; + } + for (final PotionEffect effect : new LinkedList(player.getActivePotionEffects())) { + final int id = effect.getPotionID(); + Integer cost = potionRemovalCost.get(id); + if (cost != null) { + cost *= effect.getAmplifier() + 1; + if (!ElectricItem.manager.canUse(itemStack, cost)) { + continue; + } + ElectricItem.manager.use(itemStack, 0, null); + IC2.platform.removePotion(player, id); + } + } + if (ElectricItem.manager.canUse(itemStack, 10.0) && player.getFoodStats().getFoodLevel() < 20) { + player.getFoodStats().addStats(20, 5.0F); + ElectricItem.manager.use(itemStack, 10, null); + } + IC2.platform.profilerEndSection(); + break; + } + case 2: { + IC2.platform.profilerStartSection("NanoLeggings"); + if (ElectricItem.manager.canUse(itemStack, 50.0) && IC2.keyboard.isForwardKeyDown(player) && IC2.keyboard.isBoostKeyDown(player)) { + player.stepHeight = 1.1f; + ElectricItem.manager.use(itemStack, 50.0, null); + } else player.stepHeight = 0.5f; + final boolean enableQuantumSpeedOnSprint = !IC2.platform.isRendering() || ConfigUtil.getBool(MainConfig.get(), "misc/quantumSpeedOnSprint"); + if (ElectricItem.manager.canUse(itemStack, 100.0) && (player.onGround || player.isInWater()) && IC2.keyboard.isForwardKeyDown(player) && ((enableQuantumSpeedOnSprint && player.isSprinting()) || (!enableQuantumSpeedOnSprint && IC2.keyboard.isBoostKeyDown(player)))) { + byte speedTicker = nbtData.getByte("speedTicker"); + ++speedTicker; + if (speedTicker >= 10) { + speedTicker = 0; + ElectricItem.manager.use(itemStack, 100.0, null); + ret = true; + } + nbtData.setByte("speedTicker", speedTicker); + float speed = 0.15f; + if (player.isInWater()) { + speed = 0.1f; + if (player.motionY < 0.0D) { + player.motionY *= 0.2D; + } + } + player.moveFlying(0.0f, 1.0f, speed); + } + + + IC2.platform.profilerEndSection(); + break; + } + case 3: { + IC2.platform.profilerStartSection("NanoBoots"); + if (IC2.platform.isSimulating()) { + final boolean wasOnGround = !nbtData.hasKey("wasOnGround") || nbtData.getBoolean("wasOnGround"); + if (wasOnGround && !player.onGround && IC2.keyboard.isJumpKeyDown(player) && IC2.keyboard.isBoostKeyDown(player)) { + ElectricItem.manager.use(itemStack, 4000.0, null); + ret = true; + } + if (player.onGround != wasOnGround) { + nbtData.setBoolean("wasOnGround", player.onGround); + } + } else { + if (ElectricItem.manager.canUse(itemStack, 50.0) && player.onGround) { + this.jumpCharge = 1.0f; + } + if (player.motionY >= 0.0 && this.jumpCharge > 0.0f && !player.isInWater()) { + if (IC2.keyboard.isJumpKeyDown(player) && IC2.keyboard.isBoostKeyDown(player)) { + if (this.jumpCharge == 1.0f) { + player.motionX *= 3.5; + player.motionZ *= 3.5; + } + player.motionY += this.jumpCharge * 0.25f; + this.jumpCharge *= 0.25; + } else if (this.jumpCharge < 1.0f) { + this.jumpCharge = 0.0f; + } + } + } + IC2.platform.profilerEndSection(); + break; + } + } + if (ret) { + player.inventoryContainer.detectAndSendChanges(); + } + } +} \ No newline at end of file diff --git a/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/ArmorQuantumSuit_Mixin.java b/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/ArmorQuantumSuit_Mixin.java new file mode 100644 index 0000000..56b73b5 --- /dev/null +++ b/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/ArmorQuantumSuit_Mixin.java @@ -0,0 +1,303 @@ +package space.gtimpact.mixinmodule.mixins.ic2; + +import ic2.api.item.ElectricItem; +import ic2.core.IC2; +import ic2.core.audio.PositionSpec; +import ic2.core.init.MainConfig; +import ic2.core.item.armor.ItemArmorElectric; +import ic2.core.item.armor.ItemArmorQuantumSuit; +import ic2.core.util.ConfigUtil; +import ic2.core.util.StackUtil; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.potion.Potion; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.DamageSource; +import net.minecraft.world.World; +import net.minecraftforge.common.ISpecialArmor; +import net.minecraftforge.event.entity.living.LivingFallEvent; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.LinkedList; +import java.util.Map; + +import static ic2.core.item.armor.ItemArmorQuantumSuit.audioSource; + +@Mixin(ItemArmorQuantumSuit.class) +public abstract class ArmorQuantumSuit_Mixin extends ItemArmorElectric { + + @Final + @Shadow(remap = false) + protected static Map potionRemovalCost; + @Shadow(remap = false) + private static boolean lastJetpackUsed = false; + @Shadow(remap = false) + private float jumpCharge; + + public ArmorQuantumSuit_Mixin() { + super(null, null, 0, 0, 0, 0); + } + + @Override + public double getMaxCharge(ItemStack itemStack) { + return 2.8E8D; + } + + @Override + public ArmorProperties getProperties(EntityLivingBase player, ItemStack armor, DamageSource source, double damage, int slot) { + if (source == DamageSource.fall && this.armorType == 3) { + final int energyPerDamage = player.worldObj.provider.dimensionId == 0 ? this.getEnergyPerDamage() : 100; + int damageLimit = Integer.MAX_VALUE; + if (energyPerDamage > 0) { + damageLimit = (int) Math.min(damageLimit, 25.0 * ElectricItem.manager.getCharge(armor) / energyPerDamage); + } + return new ISpecialArmor.ArmorProperties(10, 1.0, damageLimit); + } + return super.getProperties(player, armor, source, damage, slot); + } + + @Override + public void onArmorTick(final World world, final EntityPlayer player, final ItemStack itemStack) { + final NBTTagCompound nbtData = StackUtil.getOrCreateNbtData(itemStack); + byte toggleTimer = nbtData.getByte("toggleTimer"); + boolean ret = false; + switch (this.armorType) { + case 0: { + IC2.platform.profilerStartSection("QuantumHelmet"); + final int air = player.getAir(); + if (ElectricItem.manager.canUse(itemStack, 1000.0) && air < 100) { + player.setAir(air + 200); + ElectricItem.manager.use(itemStack, 1000.0, null); + ret = true; + } else if (air <= 0) { + IC2.achievements.issueAchievement(player, "starveWithQHelmet"); + } + if (ElectricItem.manager.canUse(itemStack, 10.0) && player.getFoodStats().getFoodLevel() < 20) { + player.getFoodStats().addStats(20, 5.0F); + ElectricItem.manager.use(itemStack, 10, null); + } + for (final PotionEffect effect : new LinkedList(player.getActivePotionEffects())) { + final int id = effect.getPotionID(); + Integer cost = potionRemovalCost.get(id); + if (cost != null) { + cost *= effect.getAmplifier() + 1; + if (!ElectricItem.manager.canUse(itemStack, cost)) { + continue; + } + ElectricItem.manager.use(itemStack, 0, null); + IC2.platform.removePotion(player, id); + } + } + boolean Nightvision = nbtData.getBoolean("Nightvision"); + short hubmode = nbtData.getShort("HudMode"); + if (IC2.keyboard.isAltKeyDown(player) && IC2.keyboard.isModeSwitchKeyDown(player) && toggleTimer == 0) { + toggleTimer = 10; + Nightvision = !Nightvision; + if (IC2.platform.isSimulating()) { + nbtData.setBoolean("Nightvision", Nightvision); + if (Nightvision) { + IC2.platform.messagePlayer(player, "Nightvision enabled."); + } else { + IC2.platform.messagePlayer(player, "Nightvision disabled."); + } + } + } + if (IC2.keyboard.isAltKeyDown(player) && IC2.keyboard.isHudModeKeyDown(player) && toggleTimer == 0) { + toggleTimer = 10; + if (hubmode == 2) { + hubmode = 0; + } else { + ++hubmode; + } + if (IC2.platform.isSimulating()) { + nbtData.setShort("HudMode", hubmode); + switch (hubmode) { + case 0: { + IC2.platform.messagePlayer(player, "HUD disabled."); + break; + } + case 1: { + IC2.platform.messagePlayer(player, "HUD (basic) enabled."); + break; + } + case 2: { + IC2.platform.messagePlayer(player, "HUD (extended) enabled"); + break; + } + } + } + } + if (IC2.platform.isSimulating() && toggleTimer > 0) { + --toggleTimer; + nbtData.setByte("toggleTimer", toggleTimer); + } + if (Nightvision && IC2.platform.isSimulating() && ElectricItem.manager.use(itemStack, 1.0, player)) { + final int skylight = 1; + if (skylight > 8) { + IC2.platform.removePotion(player, Potion.nightVision.id); + player.addPotionEffect(new PotionEffect(Potion.blindness.id, 100, 0, true)); + } else { + IC2.platform.removePotion(player, Potion.blindness.id); + player.addPotionEffect(new PotionEffect(Potion.nightVision.id, 300, 0, true)); + } + + ret = true; + } + IC2.platform.profilerEndSection(); + break; + } + case 1: { + IC2.platform.profilerStartSection("QuantumBodyarmor"); + boolean jetpack = nbtData.getBoolean("jetpack"); + boolean hoverMode = nbtData.getBoolean("hoverMode"); + boolean jetpackUsed = false; + if (IC2.keyboard.isJumpKeyDown(player) && IC2.keyboard.isModeSwitchKeyDown(player) && toggleTimer == 0) { + toggleTimer = 10; + hoverMode = !hoverMode; + if (IC2.platform.isSimulating()) { + nbtData.setBoolean("hoverMode", hoverMode); + if (hoverMode) { + IC2.platform.messagePlayer(player, "Quantum Hover Mode enabled."); + } else { + IC2.platform.messagePlayer(player, "Quantum Hover Mode disabled."); + } + } + } + if (IC2.keyboard.isBoostKeyDown(player) && IC2.keyboard.isModeSwitchKeyDown(player) && toggleTimer == 0) { + toggleTimer = 10; + jetpack = !jetpack; + if (IC2.platform.isSimulating()) { + nbtData.setBoolean("jetpack", jetpack); + if (jetpack) { + IC2.platform.messagePlayer(player, "Quantum Jetpack enabled."); + } else { + IC2.platform.messagePlayer(player, "Quantum Jetpack disabled."); + } + } + } + if (jetpack && (IC2.keyboard.isJumpKeyDown(player) || (hoverMode && player.motionY < -0.029999999329447746))) { + jetpackUsed = this.useJetpack(player, hoverMode); + } + if (IC2.platform.isSimulating() && toggleTimer > 0) { + --toggleTimer; + nbtData.setByte("toggleTimer", toggleTimer); + } + if (IC2.platform.isRendering() && player == IC2.platform.getPlayerInstance()) { + if (lastJetpackUsed != jetpackUsed) { + if (jetpackUsed) { + if (audioSource == null) { + audioSource = IC2.audioManager.createSource(player, PositionSpec.Backpack, "Tools/Jetpack/JetpackLoop.ogg", true, false, IC2.audioManager.getDefaultVolume()); + } + if (audioSource != null) { + audioSource.play(); + } + } else if (audioSource != null) { + audioSource.remove(); + audioSource = null; + } + lastJetpackUsed = jetpackUsed; + } + if (audioSource != null) { + audioSource.updatePosition(); + } + } + ret = jetpackUsed; + player.extinguish(); + IC2.platform.profilerEndSection(); + break; + } + case 2: { + IC2.platform.profilerStartSection("QuantumLeggings"); + final boolean enableQuantumSpeedOnSprint = !IC2.platform.isRendering() || ConfigUtil.getBool(MainConfig.get(), "misc/quantumSpeedOnSprint"); + if (ElectricItem.manager.canUse(itemStack, 150.0) && IC2.keyboard.isForwardKeyDown(player) && IC2.keyboard.isBoostKeyDown(player)) { + player.stepHeight = 3.1f; + ElectricItem.manager.use(itemStack, 150.0, null); + } else player.stepHeight = 0.5f; + if (ElectricItem.manager.canUse(itemStack, 1000.0) && (player.onGround || player.isInWater()) && IC2.keyboard.isForwardKeyDown(player) && ((enableQuantumSpeedOnSprint && player.isSprinting()) || (!enableQuantumSpeedOnSprint && IC2.keyboard.isBoostKeyDown(player)))) { + byte speedTicker = nbtData.getByte("speedTicker"); + ++speedTicker; + if (speedTicker >= 10) { + speedTicker = 0; + ElectricItem.manager.use(itemStack, 1000.0, null); + ret = true; + } + nbtData.setByte("speedTicker", speedTicker); + float speed = 0.30f; + if (player.isInWater()) { + speed = 0.1f; + if (player.motionY < 0.0D) { + player.motionY *= 0.2D; + } + } + player.moveFlying(0.0f, 1.0f, speed); + } + + IC2.platform.profilerEndSection(); + break; + } + case 3: { + IC2.platform.profilerStartSection("QuantumBoots"); + if (IC2.platform.isSimulating()) { + final boolean wasOnGround = !nbtData.hasKey("wasOnGround") || nbtData.getBoolean("wasOnGround"); + if (wasOnGround && !player.onGround && IC2.keyboard.isJumpKeyDown(player) && IC2.keyboard.isBoostKeyDown(player)) { + ElectricItem.manager.use(itemStack, 4000.0, null); + ret = true; + } + if (player.onGround != wasOnGround) { + nbtData.setBoolean("wasOnGround", player.onGround); + } + } else { + if (ElectricItem.manager.canUse(itemStack, 4000.0) && player.onGround) { + this.jumpCharge = 1.0f; + } + if (player.motionY >= 0.0 && this.jumpCharge > 0.0f && !player.isInWater()) { + if (IC2.keyboard.isJumpKeyDown(player) && IC2.keyboard.isBoostKeyDown(player)) { + if (this.jumpCharge == 1.0f) { + player.motionX *= 3.5; + player.motionZ *= 3.5; + } + player.motionY += this.jumpCharge * 0.3f; + this.jumpCharge *= 0.75; + } else if (this.jumpCharge < 1.0f) { + this.jumpCharge = 0.0f; + } + } + } + IC2.platform.profilerEndSection(); + break; + } + } + if (ret) { + player.inventoryContainer.detectAndSendChanges(); + } + } + + @Inject(method = "onEntityLivingFallEvent", at = @At("HEAD"), remap = false, cancellable = true) + public void onEntityLivingFallEvent(LivingFallEvent event, CallbackInfo ci) { + if (IC2.platform.isSimulating() && event.entity instanceof EntityLivingBase) { + final EntityLivingBase entity = (EntityLivingBase) event.entity; + final ItemStack armor = entity.getEquipmentInSlot(1); + if (armor != null && armor.getItem() == this) { + final int fallDamage = Math.max((int) event.distance - 10, 0); + final double energyCost = entity.worldObj.provider.dimensionId == 0 ? this.getEnergyPerDamage() * fallDamage : 100 * fallDamage; + if (energyCost <= ElectricItem.manager.getCharge(armor)) { + ElectricItem.manager.discharge(armor, energyCost, Integer.MAX_VALUE, true, false, false); + event.setCanceled(true); + } + } + } + ci.cancel(); + } + + @Shadow(remap = false) + public boolean useJetpack(final EntityPlayer player, final boolean hoverMode) { + throw new IllegalStateException("Mixin failed to shadow"); + } +} \ No newline at end of file diff --git a/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/BlockBase_Mixin.java b/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/BlockBase_Mixin.java new file mode 100644 index 0000000..7d425c3 --- /dev/null +++ b/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/BlockBase_Mixin.java @@ -0,0 +1,24 @@ +package space.gtimpact.mixinmodule.mixins.ic2; + +import ic2.core.block.BlockBase; +import org.spongepowered.asm.mixin.Mixin; +import net.minecraft.block.Block; + +@Mixin(BlockBase.class) +public class BlockBase_Mixin extends Block { + + + protected BlockBase_Mixin() { + super(null); + } + + @Override + public int getHarvestLevel(int metadata) { + return 0; + } + + @Override + public String getHarvestTool(int metadata) { + return "wrench"; + } +} \ No newline at end of file diff --git a/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/InvSlotConsumable_Mixin.java b/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/InvSlotConsumable_Mixin.java new file mode 100644 index 0000000..5e7415f --- /dev/null +++ b/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/InvSlotConsumable_Mixin.java @@ -0,0 +1,25 @@ +package space.gtimpact.mixinmodule.mixins.ic2; + +import ic2.core.block.invslot.InvSlotConsumable; +import ic2.core.block.invslot.InvSlotConsumableClass; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(InvSlotConsumableClass.class) +public class InvSlotConsumable_Mixin extends InvSlotConsumable { + + public InvSlotConsumable_Mixin() { + super(null, "", 0, 0); + } + + @Override + public ItemStack damage(int amount, boolean simulate) { + return super.damage(0, simulate); + } + + @Shadow(remap = false) + public boolean accepts(ItemStack itemStack) { + throw new IllegalStateException("Mixin failed to shadow testClass()"); + } +} \ No newline at end of file diff --git a/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/MiningLaser_Mixin.java b/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/MiningLaser_Mixin.java new file mode 100644 index 0000000..48244eb --- /dev/null +++ b/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/MiningLaser_Mixin.java @@ -0,0 +1,20 @@ +package space.gtimpact.mixinmodule.mixins.ic2; + +import ic2.core.item.tool.ItemElectricTool; +import ic2.core.item.tool.ItemToolMiningLaser; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(ItemToolMiningLaser.class) +public class MiningLaser_Mixin extends ItemElectricTool { + + public MiningLaser_Mixin() { + super(null, 0); + } + + @Override + public double getMaxCharge(ItemStack itemStack) { + this.maxCharge = 100000000; + return maxCharge; + } +} \ No newline at end of file diff --git a/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/NanoSaber_Mixin.java b/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/NanoSaber_Mixin.java new file mode 100644 index 0000000..415cbf6 --- /dev/null +++ b/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/NanoSaber_Mixin.java @@ -0,0 +1,21 @@ +package space.gtimpact.mixinmodule.mixins.ic2; + +import ic2.core.item.tool.ItemElectricTool; +import ic2.core.item.tool.ItemNanoSaber; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; + + +@Mixin(ItemNanoSaber.class) +public class NanoSaber_Mixin extends ItemElectricTool { + + public NanoSaber_Mixin() { + super(null, 0); + } + + @Override + public double getMaxCharge(ItemStack itemStack) { + this.maxCharge = 25000000; + return maxCharge; + } +} \ No newline at end of file diff --git a/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/ToolPainter_Mixin.java b/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/ToolPainter_Mixin.java new file mode 100644 index 0000000..f3a1122 --- /dev/null +++ b/src/main/java/space/gtimpact/mixinmodule/mixins/ic2/ToolPainter_Mixin.java @@ -0,0 +1,24 @@ +package space.gtimpact.mixinmodule.mixins.ic2; + +import ic2.core.item.ItemIC2; +import ic2.core.item.tool.ItemToolPainter; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(ItemToolPainter.class) +public abstract class ToolPainter_Mixin extends ItemIC2 { + + @Final + @Shadow(remap = false) + public int color; + + public ToolPainter_Mixin() { + super(null); + } + + @Override + public int getMaxDamage() { + return 99; + } +} \ No newline at end of file diff --git a/src/main/java/space/gtimpact/mixinmodule/mixins/vanilla/BlockHopper_Mixin.java b/src/main/java/space/gtimpact/mixinmodule/mixins/vanilla/BlockHopper_Mixin.java new file mode 100644 index 0000000..0106926 --- /dev/null +++ b/src/main/java/space/gtimpact/mixinmodule/mixins/vanilla/BlockHopper_Mixin.java @@ -0,0 +1,74 @@ +package space.gtimpact.mixinmodule.mixins.vanilla; + +import com.google.common.collect.ImmutableList; +import net.minecraft.block.Block; +import net.minecraft.block.BlockHopper; +import net.minecraft.block.material.Material; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; + +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@Mixin(BlockHopper.class) +public class BlockHopper_Mixin extends Block { + + @Unique + private static final EnumMap> bounds; + + static { + List commonBounds = ImmutableList.of( + makeAABB(0, 10, 0, 16, 16, 16), + makeAABB(4, 4, 4, 12, 10, 12) + ); + bounds = (EnumMap) Stream.of(EnumFacing.values()).filter((t) -> t != EnumFacing.UP).collect(Collectors.toMap((a) -> { + return a; + }, (a) -> { + return new ArrayList(commonBounds); + }, (u, v) -> { + throw new IllegalStateException(); + }, () -> { + return new EnumMap(EnumFacing.class); + })); + bounds.get(EnumFacing.DOWN).add(makeAABB(6, 0, 6, 10, 4, 10)); + bounds.get(EnumFacing.NORTH).add(makeAABB(6, 4, 0, 10, 8, 4)); + bounds.get(EnumFacing.SOUTH).add(makeAABB(6, 4, 12, 10, 8, 16)); + bounds.get(EnumFacing.WEST).add(makeAABB(0, 4, 6, 4, 8, 10)); + bounds.get(EnumFacing.EAST).add(makeAABB(12, 4, 6, 16, 8, 10)); + } + + protected BlockHopper_Mixin(Material p_i45394_1_) { + super(p_i45394_1_); + } + + private static AxisAlignedBB makeAABB(int fromX, int fromY, int fromZ, int toX, int toY, int toZ) { + return AxisAlignedBB.getBoundingBox((float) fromX / 16.0F, (float) fromY / 16.0F, (float) fromZ / 16.0F, (float) toX / 16.0F, (float) toY / 16.0F, (float) toZ / 16.0F); + } + + private static MovingObjectPosition rayTrace(Vec3 pos, Vec3 start, Vec3 end, AxisAlignedBB boundingBox) { + Vec3 vec3d = start.addVector(-pos.xCoord, -pos.yCoord, -pos.zCoord); + Vec3 vec3d1 = end.addVector(-pos.xCoord, -pos.yCoord, -pos.zCoord); + MovingObjectPosition raytraceresult = boundingBox.calculateIntercept(vec3d, vec3d1); + if (raytraceresult == null) { + return null; + } else { + Vec3 res = raytraceresult.hitVec.addVector(pos.xCoord, pos.yCoord, pos.zCoord); + return new MovingObjectPosition((int) res.xCoord, (int) res.yCoord, (int) res.zCoord, raytraceresult.sideHit, pos); + } + } + + public MovingObjectPosition collisionRayTrace(World world, int x, int y, int z, Vec3 start, Vec3 end) { + Vec3 pos = Vec3.createVectorHelper(x, y, z); + EnumFacing facing = EnumFacing.values()[BlockHopper.getDirectionFromMetadata(world.getBlockMetadata(x, y, z))]; + return ((List) bounds.get(facing)).stream().map((bb) -> rayTrace(pos, start, end, (AxisAlignedBB) bb)).anyMatch(Objects::nonNull) ? super.collisionRayTrace(world, x, y, z, start, end) : null; + } +} \ No newline at end of file diff --git a/src/main/java/space/gtimpact/mixinmodule/mixins/vanilla/ForgeHooksClient_Mixin.java b/src/main/java/space/gtimpact/mixinmodule/mixins/vanilla/ForgeHooksClient_Mixin.java new file mode 100644 index 0000000..6dab276 --- /dev/null +++ b/src/main/java/space/gtimpact/mixinmodule/mixins/vanilla/ForgeHooksClient_Mixin.java @@ -0,0 +1,40 @@ +package space.gtimpact.mixinmodule.mixins.vanilla; + +import net.minecraft.client.main.Main; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.client.ForgeHooksClient; +import org.lwjgl.opengl.Display; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; + +@Mixin(ForgeHooksClient.class) +public class ForgeHooksClient_Mixin { + + @Inject(method = "createDisplay", at = @At("HEAD"), remap = false) + private static void createDisplay(CallbackInfo ci) { + Display.setTitle("IMPACT GREGTECH EDITION"); + ResourceLocation icon = new ResourceLocation("impact", "textures/gui/title/fav.png"); + try { + InputStream inputstream = Main.class.getResourceAsStream("/assets/" + icon.getResourceDomain() + "/" + icon.getResourcePath()); + Display.setIcon(new ByteBuffer[]{call(inputstream)}); + } catch (IOException ignore) { + } + } + + private static ByteBuffer call(InputStream is) throws IOException { + BufferedImage bufferedimage = ImageIO.read(is); + int[] aint = bufferedimage.getRGB(0, 0, bufferedimage.getWidth(), bufferedimage.getHeight(), null, 0, bufferedimage.getWidth()); + ByteBuffer bytebuffer = ByteBuffer.allocate(4 * aint.length); + for (int k : aint) bytebuffer.putInt(k << 8 | k >> 24 & 255); + bytebuffer.flip(); + return bytebuffer; + } +} \ No newline at end of file