From fea240e320c411b6e624290e7d3f15a7dd1852b9 Mon Sep 17 00:00:00 2001 From: LRW-Calen Date: Fri, 17 May 2024 01:34:29 +0800 Subject: [PATCH 1/5] 1.16.5 --- .gitignore | 38 +- build.gradle | 470 +++++++++--------- build.properties | 27 +- common/buildcraft/compat/BCCompat.java | 187 +++---- .../buildcraft/compat/CompatModuleBase.java | 5 +- common/buildcraft/compat/CompatUtils.java | 27 +- .../module/crafttweaker/AssemblyTable.java | 209 +++++--- .../module/crafttweaker/CombustionEngine.java | 274 +++++----- .../CompatModuleCraftTweaker.java | 12 +- .../compat/module/crafttweaker/Coolant.java | 132 +++++ .../module/forestry/CompatModuleForestry.java | 39 -- .../module/forestry/list/ListMatchGenome.java | 93 ---- .../forestry/pipe/ContainerPropolisPipe.java | 22 - .../module/forestry/pipe/ForestryPipes.java | 86 ---- .../forestry/pipe/PipeBehaviourPropolis.java | 196 -------- .../ic2/CompatModuleIndustrialCraft2.java | 27 +- .../compat/module/jei/BCPluginJEI.java | 249 ++++++---- .../CategoryCombustionEngine.java | 158 ++++-- .../HandlerCombustionEngine.java | 19 - .../WrapperCombustionEngine.java | 110 ---- .../energy/combustionengine/package-info.java | 3 +- .../module/jei/factory/CategoryCoolable.java | 119 +++-- .../module/jei/factory/CategoryDistiller.java | 126 +++-- .../module/jei/factory/CategoryHeatable.java | 116 ++++- .../module/jei/factory/HandlerCoolable.java | 15 - .../module/jei/factory/HandlerDistiller.java | 15 - .../module/jei/factory/HandlerHeatable.java | 15 - .../module/jei/factory/WrapperCoolable.java | 86 ---- .../module/jei/factory/WrapperDistiller.java | 84 ---- .../module/jei/factory/WrapperHeatable.java | 84 ---- .../module/jei/factory/package-info.java | 3 +- .../module/jei/gui/GuiHandlerBuildCraft.java | 46 ++ .../module/jei/recipe/GateGuiHandler.java | 37 -- .../jei/recipe/GuiHandlerBuildCraft.java | 51 -- .../jei/recipe/HandlerFlexibleRecipe.java | 15 - .../module/jei/recipe/LedgerGuiHandler.java | 35 -- .../jei/silicon/CategoryAssemblyTable.java | 139 ++++-- .../jei/silicon/CategoryIntegrationTable.java | 125 +++-- .../jei/silicon/HandlerIntegrationTable.java | 38 -- .../compat/module/jei/silicon/Utils.java | 10 +- .../jei/silicon/WrapperAssemblyTable.java | 83 ---- .../jei/silicon/WrapperIntegrationTable.java | 93 ---- .../module/jei/silicon/package-info.java | 3 +- .../AdvancedCraftingItemsTransferHandler.java | 30 +- .../AssemblyTableTransferHandler.java | 12 +- .../AutoCraftItemsTransferHandler.java | 42 +- .../jei/transferhandlers/package-info.java | 3 +- .../module/theoneprobe/BCPluginTOP.java | 122 ++--- .../theoneprobe/CompatModuleTheOneProbe.java | 11 +- .../waila/AssemblyCraftDataProvider.java | 51 ++ .../module/waila/AutoCraftDataProvider.java | 112 ++--- .../module/waila/BaseWailaDataProvider.java | 66 +-- .../compat/module/waila/HWYLAPlugin.java | 65 ++- .../module/waila/LaserTargetDataProvider.java | 72 ++- .../buildcraft/compat/network/CompatGui.java | 304 +++++------ .../compat/network/IGuiCreator.java | 24 +- gradle.properties | 4 + gradle/wrapper/gradle-wrapper.jar | Bin 53556 -> 59203 bytes gradle/wrapper/gradle-wrapper.properties | 12 +- resources/META-INF/mods.toml_ | 32 ++ .../assets/buildcraftcompat/lang/de_DE.lang | 20 - .../assets/buildcraftcompat/lang/de_de.json | 24 + .../assets/buildcraftcompat/lang/en_US.lang | 25 - .../assets/buildcraftcompat/lang/en_us.json | 45 ++ .../assets/buildcraftcompat/lang/fr_FR.lang | 20 - .../assets/buildcraftcompat/lang/fr_fr.json | 24 + .../assets/buildcraftcompat/lang/ko_KR.lang | 20 - .../assets/buildcraftcompat/lang/ko_kr.json | 24 + .../assets/buildcraftcompat/lang/pt_BR.lang | 20 - .../assets/buildcraftcompat/lang/pt_br.json | 24 + .../assets/buildcraftcompat/lang/ru_RU.lang | 25 - .../assets/buildcraftcompat/lang/ru_ru.json | 29 ++ .../assets/buildcraftcompat/lang/uk_UA.lang | 20 - .../assets/buildcraftcompat/lang/uk_ua.json | 24 + .../assets/buildcraftcompat/lang/zh_CN.lang | 20 - .../assets/buildcraftcompat/lang/zh_cn.json | 40 ++ resources/mcmod.info | 16 - 77 files changed, 2404 insertions(+), 2699 deletions(-) create mode 100644 common/buildcraft/compat/module/crafttweaker/Coolant.java delete mode 100644 common/buildcraft/compat/module/forestry/CompatModuleForestry.java delete mode 100644 common/buildcraft/compat/module/forestry/list/ListMatchGenome.java delete mode 100644 common/buildcraft/compat/module/forestry/pipe/ContainerPropolisPipe.java delete mode 100644 common/buildcraft/compat/module/forestry/pipe/ForestryPipes.java delete mode 100644 common/buildcraft/compat/module/forestry/pipe/PipeBehaviourPropolis.java delete mode 100644 common/buildcraft/compat/module/jei/energy/combustionengine/HandlerCombustionEngine.java delete mode 100644 common/buildcraft/compat/module/jei/energy/combustionengine/WrapperCombustionEngine.java delete mode 100644 common/buildcraft/compat/module/jei/factory/HandlerCoolable.java delete mode 100644 common/buildcraft/compat/module/jei/factory/HandlerDistiller.java delete mode 100644 common/buildcraft/compat/module/jei/factory/HandlerHeatable.java delete mode 100644 common/buildcraft/compat/module/jei/factory/WrapperCoolable.java delete mode 100644 common/buildcraft/compat/module/jei/factory/WrapperDistiller.java delete mode 100644 common/buildcraft/compat/module/jei/factory/WrapperHeatable.java create mode 100644 common/buildcraft/compat/module/jei/gui/GuiHandlerBuildCraft.java delete mode 100644 common/buildcraft/compat/module/jei/recipe/GateGuiHandler.java delete mode 100644 common/buildcraft/compat/module/jei/recipe/GuiHandlerBuildCraft.java delete mode 100644 common/buildcraft/compat/module/jei/recipe/HandlerFlexibleRecipe.java delete mode 100644 common/buildcraft/compat/module/jei/recipe/LedgerGuiHandler.java delete mode 100644 common/buildcraft/compat/module/jei/silicon/HandlerIntegrationTable.java delete mode 100644 common/buildcraft/compat/module/jei/silicon/WrapperAssemblyTable.java delete mode 100644 common/buildcraft/compat/module/jei/silicon/WrapperIntegrationTable.java create mode 100644 common/buildcraft/compat/module/waila/AssemblyCraftDataProvider.java create mode 100644 gradle.properties create mode 100644 resources/META-INF/mods.toml_ delete mode 100644 resources/assets/buildcraftcompat/lang/de_DE.lang create mode 100644 resources/assets/buildcraftcompat/lang/de_de.json delete mode 100644 resources/assets/buildcraftcompat/lang/en_US.lang create mode 100644 resources/assets/buildcraftcompat/lang/en_us.json delete mode 100644 resources/assets/buildcraftcompat/lang/fr_FR.lang create mode 100644 resources/assets/buildcraftcompat/lang/fr_fr.json delete mode 100644 resources/assets/buildcraftcompat/lang/ko_KR.lang create mode 100644 resources/assets/buildcraftcompat/lang/ko_kr.json delete mode 100644 resources/assets/buildcraftcompat/lang/pt_BR.lang create mode 100644 resources/assets/buildcraftcompat/lang/pt_br.json delete mode 100644 resources/assets/buildcraftcompat/lang/ru_RU.lang create mode 100644 resources/assets/buildcraftcompat/lang/ru_ru.json delete mode 100644 resources/assets/buildcraftcompat/lang/uk_UA.lang create mode 100644 resources/assets/buildcraftcompat/lang/uk_ua.json delete mode 100644 resources/assets/buildcraftcompat/lang/zh_CN.lang create mode 100644 resources/assets/buildcraftcompat/lang/zh_cn.json delete mode 100644 resources/mcmod.info diff --git a/.gitignore b/.gitignore index 5e19125..f73156f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,26 +1,44 @@ -#eclipse -.project -.classpath -.metadata -org.* +# eclipse bin *.launch +.settings +.metadata +.classpath +.project +eclipse -#idea -*.iml +# idea +out *.ipr *.iws +*.iml .idea -out -#gradle +# gradle build .gradle +modules libs #runtime run -classes +run_server #mac .DS_Store + +#Custom code to inject the the dev environment +custom +test-results + +#licnse_checker +# Not in git because it contains names + emails. +license_checker/agreed.txt +license_checker/unused_code.txt +license_checker/out/** + +# Files from Forge MDK +forge*changelog.txt + +# For some annoying reason the tests creates a log file in "/logs/latest.txt" +logs diff --git a/build.gradle b/build.gradle index 95cf589..af4be14 100755 --- a/build.gradle +++ b/build.gradle @@ -1,31 +1,20 @@ -// DON'T TOUCH THE BUILDSCRIPT[] BLOCK -// its special, and it is only there to make ForgeGradle work correctly. - buildscript { repositories { + maven { url = 'https://maven.minecraftforge.net' } mavenCentral() - maven { - name = "forge" - url = "http://files.minecraftforge.net/maven" - } - maven { - name = "sonatype" - url = "https://oss.sonatype.org/content/repositories/snapshots/" - } - maven { - url "https://plugins.gradle.org/m2/" - } } dependencies { - classpath "net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT" - classpath "org.ajoberstar:grgit:2.2.1" + classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '5.1.+', changing: true + + classpath 'org.spongepowered:mixingradle:0.7.+' + classpath 'javax.vecmath:vecmath:1.5.2' } } -apply plugin: "net.minecraftforge.gradle.forge" // adds the forge dependency -apply plugin: "maven" // for uploading to a maven repo -apply plugin: 'maven-publish' // for uploading to a maven repo -apply plugin: "org.ajoberstar.grgit" +apply plugin: 'net.minecraftforge.gradle' +// Only edit below this line, the above code adds and enables the necessary things for Forge to be setup. +apply plugin: 'eclipse' +apply plugin: 'maven-publish' ext.configFile = file "build.properties" configFile.withReader { @@ -40,268 +29,297 @@ configFile.withReader { } version = config.compat_version +// version = config.compat_version + "-" + new Date().format("yyyy-MM-dd'T'HH-mm-ssZ") group = "com.mod-buildcraft-compat" archivesBaseName = "buildcraft" // the name that all artifacts will use as a base. artifacts names follow this pattern: [baseName]-[appendix]-[version]-[classifier].[extension] -ext { - compatModInfo = new groovy.json.JsonSlurper().parse(file("resources/mcmod.info")) - mainModInfo = new groovy.json.JsonSlurper().parse(file("BuildCraft/buildcraft_resources/mcmod.info")) -} - -sourceCompatibility = 1.8 -targetCompatibility = 1.8 - -repositories { - maven { name="JEI"; url="http://dvs1.progwml6.com/files/maven" } - maven { name="TOP"; url="http://maven.tterrag.com/" } - maven { name="hwyla"; url="http://tehnut.info/maven" } - // The One probe depends on the RF API -- we don't use it ourselves, nor will we ever add compat for it... - maven { name="cofh"; url="http://maven.covers1624.net" } - maven { name="forestry"; url = "http://maven.ic2.player.to/" } - maven { name "CraftTweaker"; url "http://maven.blamejared.com/" } -} - -dependencies { - // JEI Stuff - // Versions from http://minecraft.curseforge.com/projects/just-enough-items-jei/files - compileOnly "mezz.jei:jei_${config.mc_version}:${config.jei_version}:api" - runtime "mezz.jei:jei_${config.mc_version}:${config.jei_version}" - - // The One Probe Stuff - compileOnly "mcjty.theoneprobe:TheOneProbe-1.12:${config.top_version}:api" - runtime "mcjty.theoneprobe:TheOneProbe-1.12:${config.top_version}" - // The One Probe depends on the RF api for some odd reason... we never intend to add support for RF ourselves though. - - // HWYLA - compileOnly "mcp.mobius.waila:Hwyla:${config.hwyla_version}:api" - runtime "mcp.mobius.waila:Hwyla:${config.hwyla_version}" - - // Forestry - deobfCompile "net.sengir.forestry:forestry_${config.mc_version}:${config.forestry_version}" - - deobfCompile "net.industrial-craft:industrialcraft-2:${config.ic2_version}" - - // CraftTweaker - deobfCompile "CraftTweaker2:CraftTweaker2-API:${config.crafttweaker_version}" - deobfCompile "CraftTweaker2:CraftTweaker2-MC1120-Main:1.12-${config.crafttweaker_version}" -} +java.toolchain.languageVersion = JavaLanguageVersion.of(8) // Mojang ships Java 8 to end users, so your mod should target Java 8. +println('Java: ' + System.getProperty('java.version') + ' JVM: ' + System.getProperty('java.vm.version') + '(' + System.getProperty('java.vendor') + ') Arch: ' + System.getProperty('os.arch')) minecraft { - version = config.mc_version + "-" + config.forge_version - runDir = "run" - - // the mappings can be changed at any time, and must be in the following format. - // snapshot_YYYYMMDD snapshot are built nightly. - // stable_# stables are built at the discretion of the MCP team. - // Use non-default mappings at your own risk. they may not allways work. - // simply re-run your setup task after changing the mappings to update your workspace. - mappings = config.mappings_version - - useDepAts = true - - def separate = Boolean.getBoolean("build_compat_only") - if (separate) { - project.version = config.compat_version - } else { - project.version = config.mod_version; - } - - def addVersionDetails = !Boolean.getBoolean("release") - - // Git versioning stuffs - if (grgit != null) { - def repo = grgit.open(dir: project.rootDir) - replace "\${git_commit_hash}", repo.head().id - replace "\${git_commit_msg}", repo.head().fullMessage.replace("\"", "\\\\\\\"").split("\n")[0] - replace "\${git_commit_author}", repo.head().author.name - replace "\${git_branch}", repo.branch.current().getName() - if (addVersionDetails) { - project.version += "-" + repo.head().id.toString().substring(0, 12) - } - } else { - if (addVersionDetails) { - project.version += "-SNAPSHOT" - } - } - + // The mappings can be changed at any time, and must be in the following format. + // Channel: Version: + // snapshot YYYYMMDD Snapshot are built nightly. + // stable # Stables are built at the discretion of the MCP team. + // official MCVersion Official field/method names from Mojang mapping files + // + // You must be aware of the Mojang license when using the 'official' mappings. + // See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md + // + // Use non-default mappings at your own risk. they may not always work. + // Simply re-run your setup task after changing the mappings to update your workspace. + mappings channel: 'official', version: '1.16.5' // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. - // replacing stuff in the source - replace "\$version", project.version - replace "\${mcversion}", version - // Replace @Mod.acceptedMinecraftVersions specially as it has to be a valid version in a dev environment :/ - replace "(gradle_replace_mcversion,)", "[" + version + "]" - replace "(gradle_replace_forgeversion,)", "[" + config.forge_version + ",)" - replace "\$bc_version", config.mod_version - - useDepAts = true -} - -compileJava { - options.compilerArgs << "-Xmaxerrs" << "2000" - options.compilerArgs << "-Xmaxwarns" << "2" - options.compilerArgs << "-Xlint:all" - options.compilerArgs << "-Xdiags:verbose" - options.compilerArgs << "-encoding" << "UTF-8" -} + accessTransformer = file('BuildCraft/buildcraft_resources/META-INF/accesstransformer.cfg') + + // Default run configurations. + // These can be tweaked, removed, or duplicated as needed. + runs { + client { + workingDirectory project.file('run') + + // Recommended logging data for a userdev environment + // The markers can be changed as needed. + // "SCAN": For mods scan. + // "REGISTRIES": For firing of registry events. + // "REGISTRYDUMP": For getting the contents of all registries. + property 'forge.logging.markers', 'REGISTRIES' + + // Recommended logging level for the console + // You can set various levels here. + // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels + property 'forge.logging.console.level', 'debug' + + mods { + buildcraftcore { + source sourceSets.main + } + } + } -javadoc { - options.setUse(true) - options.addStringsOption("Xmaxerrs").setValue(["2000"]) - options.addStringsOption("Xmaxwarns").setValue(["2000"]) - options.addStringsOption("Xdoclint:all") - options.setEncoding("UTF-8") -} + server { + workingDirectory project.file('run_server') + + // Recommended logging data for a userdev environment + // The markers can be changed as needed. + // "SCAN": For mods scan. + // "REGISTRIES": For firing of registry events. + // "REGISTRYDUMP": For getting the contents of all registries. + property 'forge.logging.markers', 'REGISTRIES' + + // Recommended logging level for the console + // You can set various levels here. + // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels + property 'forge.logging.console.level', 'debug' + + mods { + buildcraftcore { + source sourceSets.main + } + } + } -task setupSubProjects(dependsOn: "BuildCraft:sub_projects:expression:generateSources") { - // Just an inter-dependency task + data { + workingDirectory project.file('run') + + // Recommended logging data for a userdev environment + // The markers can be changed as needed. + // "SCAN": For mods scan. + // "REGISTRIES": For firing of registry events. + // "REGISTRYDUMP": For getting the contents of all registries. + property 'forge.logging.markers', 'REGISTRIES' + + // Recommended logging level for the console + // You can set various levels here. + // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels + property 'forge.logging.console.level', 'debug' + + // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. + args '--mod', 'buildcraftcore', '--all', '--output', file('BuildCraft/buildcraft_resources_generated/'), '--existing', file('BuildCraft/buildcraft_resources/') + + mods { + buildcraftcore { + source sourceSets.main + } + } + } + } } -eclipseClasspath.dependsOn setupSubProjects -ideaModule.dependsOn setupSubProjects -compileApiJava.dependsOn setupSubProjects - -// configure the source folders +// Include resources generated by data generators. sourceSets { - api { + main { java { + srcDir "common" srcDir "BuildCraft/BuildCraftAPI/api" srcDir "BuildCraft/common" srcDir "BuildCraft/sub_projects/expression/src/main/java" srcDir "BuildCraft/sub_projects/expression/src/autogen/java" } resources { + srcDir "resources" srcDir "BuildCraft/buildcraft_resources" + srcDir 'BuildCraft/buildcraft_resources_generated' + srcDir "BuildCraft/BuildCraft-Localization" srcDir "BuildCraft/BuildCraftGuide/guide_resources" + exclude "**/.md" // exclude readme from localization repo exclude "pack.png" // exclude from the guide repo - exclude "pack.mcmeta" // exclude from the guide repo + // Calen: we should not exclude the pack.mcmeta file in buildcraft_resources, or all the resources will be lost +// exclude "pack.mcmeta" // exclude from the guide repo } } - main { + api { java { - srcDir "common" + srcDir "BuildCraft/BuildCraftAPI/api" + srcDir "BuildCraft/common" + srcDir "BuildCraft/sub_projects/expression/src/main/java" + srcDir "BuildCraft/sub_projects/expression/src/autogen/java" } resources { - srcDir "resources" + srcDir "BuildCraft/buildcraft_resources" + srcDir "BuildCraft/BuildCraftGuide/guide_resources" + exclude "pack.png" // exclude from the guide repo + // exclude "pack.mcmeta" // exclude from the guide repo + } + } + test { + java { + srcDir "BuildCraft/src/test/java" + srcDir "BuildCraft/sub_projects/expression/src/test/java" } } } -// Obfuscated Jar location -ext.jarFile = zipTree(jar.archivePath) - -processResources { - // replace stuff in mcmod.info, nothing else - from(sourceSets.main.resources.srcDirs) { - include 'mcmod.info' +repositories { + // Put repositories for dependencies here + // ForgeGradle automatically adds the Forge maven and Maven Central for you - // replace version and mcversion - // ${version} and ${mcversion} are the exact strings being replaced - expand 'version': project.version, 'mcversion': project.minecraft.version, 'modid': config.modid + // If you have mod jar dependencies in ./libs, you can declare them as a repository like so: + flatDir { + dir 'libs' } - // copy everything else, that's not the mcmod.info - from(sourceSets.main.resources.srcDirs) { - exclude 'mcmod.info' - exclude 'pack.mcmeta' - exclude 'pack.png' + maven { + name 'prog' + url 'https://dvs1.progwml6.com/files/maven' + content { + includeGroup 'mezz.jei' + } } -} - -def createAllModInfo() { - return new File("$projectDir/build/processing/compat-all/mcmod.info") -} - -task writeAllModInfo() { - outputs.upToDateWhen { false } - doLast { - File temp = createAllModInfo() - temp.parentFile.mkdirs() - if (temp.exists()) - temp.delete() - temp.createNewFile() - def elements = []; - for (int i = 0; i < mainModInfo.size(); i++) { - elements += mainModInfo[i]; + maven { + name 'CurseMaven' + url 'https://www.cursemaven.com' + content { + includeGroup 'curse.maven' + } + } + // JEI + maven { + // location of the maven that hosts JEI files before January 2023 + name = "Progwml6's maven" + url = "https://dvs1.progwml6.com/files/maven/" + } + maven { + // location of the maven that hosts JEI files since January 2023 + name = "Jared's maven" + url = "https://maven.blamejared.com/" + } + maven { + // location of a maven mirror for JEI files, as a fallback + name = "ModMaven" + url = "https://modmaven.dev" + } + // crafttweaker + maven { + name 'CraftTweaker' + url "https://maven.blamejared.com" + content { + includeGroup 'com.blamejared.crafttweaker' + } + } + // TOP + maven { + name 'tterrag' + url 'https://maven.tterrag.com/' + content { + includeGroup 'mcjty.theoneprobe' + includeGroup 'team.chisel.ctm' } - elements += compatModInfo[0]; - String prettyPrinted = groovy.json.JsonOutput.prettyPrint(groovy.json.JsonOutput.toJson(elements)) - prettyPrinted = prettyPrinted.replace("\$version", project.version) - prettyPrinted = prettyPrinted.replace("\${mcversion}", project.minecraft.version) - temp.write(prettyPrinted) - return temp } +// maven { +// name 'tterrag maven' +// url "https://maven.tterrag.com/" +// } } -def unzippedSourceJar = new File("$projectDir/build/processing/tasks/unzipped_src_jar/unzip") -def libsDir = new File(System.getenv("LIBS_DIR") ?: "build/libs/", project.version) -def modulesDir = new File(libsDir, "modules") +dependencies { + // Specify the version of Minecraft to use, If this is any group other then 'net.minecraft' it is assumed + // that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied. + // The userdev artifact is a special name and will get all sorts of transformations applied to it. + minecraft 'net.minecraftforge:forge:1.16.5-36.2.34' -// forge (or gradle?) creates a special sourceJar which has been processed -// This task unzips that created jar, so that partial source jars can be created. -task unzipSourceJar(type: Copy, dependsOn: sourceJar) { - from (zipTree(sourceJar.archivePath)) { - include "**" - } - into unzippedSourceJar -} + // Examples using mod jars from ./libs -task compatJar(type: Jar, dependsOn:reobfJar) { - destinationDir = modulesDir - appendix = "compat" - version = project.version + compileOnly fg.deobf("mezz.jei:jei-" + config.mc_version + ":" + config.jei_version + ":api") + runtimeOnly fg.deobf("mezz.jei:jei-" + config.mc_version + ":" + config.jei_version) - from(project.ext.jarFile) { - includes.addAll("**") - } -} + compileOnly fg.deobf("curse.maven:jade-324717:3467445") + runtimeOnly fg.deobf("curse.maven:jade-324717:3467445") + +// compileOnly fg.deobf("blank:ae2-${mc_version}:11.7.6") +// runtimeOnly fg.deobf("blank:ae2-${mc_version}:11.7.6") -task allJar(type: Jar, dependsOn: [reobfJar, writeAllModInfo]) { - destinationDir = libsDir - appendix = "all" - version = project.version + compileOnly fg.deobf("com.blamejared.crafttweaker:CraftTweaker-1.16.5:7.1.2.479") + runtimeOnly fg.deobf("com.blamejared.crafttweaker:CraftTweaker-1.16.5:7.1.2.479") - from(createAllModInfo().parentFile) - from(project.ext.jarFile) { - includes.addAll("**") - exclude("mcmod.info") + compileOnly fg.deobf("mcjty.theoneprobe:TheOneProbe-1.16:1.16-3.1.4-22:api") + runtimeOnly fg.deobf("mcjty.theoneprobe:TheOneProbe-1.16:1.16-3.1.4-22") + +// runtimeOnly fg.deobf("net.sengir.forestry:forestry_${minecraft_version}:${forestry_version}") +// runtimeOnly fg.deobf("net.sengir.forestry:forestry_${minecraft_version}:${forestry_version}") + + compileOnly("javax.vecmath:vecmath:1.5.2") + runtimeOnly("javax.vecmath:vecmath:1.5.2") + compileOnly("net.sf.trove4j:trove4j:3.0.3") + runtimeOnly("net.sf.trove4j:trove4j:3.0.3") + + jarJar(group: 'net.sf.trove4j', name: 'trove4j', version: '[3.0.3,)') { + jarJar.pin(it, '3.0.3') + } + jarJar(group: 'javax.vecmath', name: 'vecmath', version: '[1.5.2,)') { + jarJar.pin(it, '1.5.2') } -} -task allSrcJar(type: Jar, dependsOn:[reobfJar, writeAllModInfo, unzipSourceJar]) { - destinationDir = libsDir - appendix = "all" - classifier = "sources" + // Testing + testImplementation "junit:junit:4.12" + testImplementation 'org.hamcrest:hamcrest:2.2' +// compileOnly "junit:junit:4.12" - from(createAllModInfo().parentFile) - from(unzippedSourceJar) { - includes.add("**") - exclude("mcmod.info") + annotationProcessor 'org.spongepowered:mixin:0.8.5:processor' +} + +// Example for how to get properties into the manifest for reading by the runtime.. +jar { + manifest { + attributes([ + "Specification-Title": "BuildCraft", + "Specification-Vendor": "BuildCraft Team", + "Specification-Version": project.version, + "Implementation-Title": project.name, + "Implementation-Version": project.jar.archiveVersion, + "Implementation-Vendor" :"BuildCraft Team", + "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"), + "MixinConfigs" : "mixins.buildcraft.json" + ]) } + include '**/**/**/libs/*' } -build.dependsOn compatJar, allJar, allSrcJar +// Example configuration to allow publishing using the maven-publish task +// This is the preferred method to reobfuscate your jar file +jar.finalizedBy('reobfJar') +// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing +//publish.dependsOn('reobfJar') publishing { + publications { + mavenJava(MavenPublication) { + artifact jar + } + } repositories { maven { - url System.getenv("MAVEN_DIR") ?: "$projectDir/build/maven" + url "file:///${project.projectDir}/mcmodsrepo" } } - publications { - pub_allJar(MavenPublication) { - groupId "com.mod-buildcraft" - artifactId "buildcraft-all" - version project.version +} - artifact allJar - } - pub_apiSrcJar(MavenPublication) { - groupId "com.mod-buildcraft" - artifactId "buildcraft-all" - version project.version +jar.enabled = true - artifact allSrcJar - } - } +// enable Jar-in-Jar +jarJar.enable() + +tasks.named('jarJar') { + // ... } diff --git a/build.properties b/build.properties index 66c247b..57783a3 100644 --- a/build.properties +++ b/build.properties @@ -1,8 +1,25 @@ -compat_version=7.99.15 +# mc_version=1.12.2 +mc_version=1.16.5 +# forge_version=14.23.0.2544 +forge_version=36.2.34 +# mappings_version=snapshot_20171120 +mappings_channel=official +mappings_version=1.16.5 +# mod_version=7.99.24.8 +mod_version=7.99.24.9 +#compat_version=7.99.15 +compat_version=7.99.24.9 + +#jei_version=4.8.5.138 +jei_version=7.8.0.1011 +#top_version=1.12-1.4.19-11 +top_version=1.16-3.0.8-14 +#hwyla_version=1.8.22-B37_1.12 + +jade_api_id=3803228 +jade_id=3803226 -jei_version=4.8.5.138 -top_version=1.12-1.4.19-11 -hwyla_version=1.8.22-B37_1.12 forestry_version=5.7.0.236 -crafttweaker_version=4.1.9.491 +#crafttweaker_version=4.1.9.491 +crafttweaker_version=7.1.2.527 ic2_version=2.8.221-ex112 diff --git a/common/buildcraft/compat/BCCompat.java b/common/buildcraft/compat/BCCompat.java index 72fdbaa..ef00fd9 100644 --- a/common/buildcraft/compat/BCCompat.java +++ b/common/buildcraft/compat/BCCompat.java @@ -1,53 +1,48 @@ -/* - * Copyright (c) 2020 SpaceToad and the BuildCraft team - * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not - * distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/ - */ - package buildcraft.compat; -import java.util.HashMap; -import java.util.Map; - -import net.minecraftforge.common.config.Property; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.common.event.FMLInitializationEvent; -import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; -import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; -import net.minecraftforge.fml.common.network.NetworkRegistry; - +import buildcraft.api.BCModules; import buildcraft.api.core.BCLog; - import buildcraft.compat.module.crafttweaker.CompatModuleCraftTweaker; -import buildcraft.compat.module.forestry.CompatModuleForestry; import buildcraft.compat.module.ic2.CompatModuleIndustrialCraft2; import buildcraft.compat.module.theoneprobe.CompatModuleTheOneProbe; -import buildcraft.compat.network.CompatGui; -import buildcraft.core.BCCoreConfig; +import buildcraft.lib.config.BCConfig; +import buildcraft.lib.config.Configuration; +import buildcraft.lib.config.EnumRestartRequirement; +import net.minecraftforge.common.ForgeConfigSpec; +import net.minecraftforge.common.ForgeConfigSpec.BooleanValue; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.ModContainer; +import net.minecraftforge.fml.ModList; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.config.ModConfig; +import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; +import net.minecraftforge.fml.event.lifecycle.FMLConstructModEvent; +import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent; -//@formatter:off -@Mod( - modid = BCCompat.MODID, - name = "BuildCraft Compat", - version = BCCompat.VERSION, - updateJSON = "https://mod-buildcraft.com/version/versions-compat.json", - acceptedMinecraftVersions = "(gradle_replace_mcversion,)", - dependencies = BCCompat.DEPENDENCIES -) -//@formatter:on -public class BCCompat { +import java.util.HashMap; +import java.util.Map; +//@Mod( +// modid = "buildcraftcompat", +// name = "BuildCraft Compat", +// version = "7.99.24.8", +// updateJSON = "https://mod-buildcraft.com/version/versions-compat.json", +// acceptedMinecraftVersions = "[1.12.2]", +// dependencies = "required-after:forge@[14.23.0.2544,);required-after:buildcraftcore@[7.99.24.8,);after:buildcrafttransport;after:buildcraftbuilders;after:buildcraftsilicon;after:theoneprobe;after:forestry;after:crafttweaker;after:ic2" +//) +@Mod(BCCompat.MODID) +@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) +public class BCCompat { static final String DEPENDENCIES = "required-after:forge@(gradle_replace_forgeversion,)"// - + ";required-after:buildcraftcore@[$bc_version,)"// - + ";after:buildcrafttransport"// - + ";after:buildcraftbuilders"// - + ";after:buildcraftsilicon"// - + ";after:theoneprobe"// - + ";after:forestry"// - + ";after:crafttweaker"// - + ";after:ic2"// - ; - + + ";required-after:buildcraftcore@[$bc_version,)"// + + ";after:buildcrafttransport"// + + ";after:buildcraftbuilders"// + + ";after:buildcraftsilicon"// + + ";after:theoneprobe"// + + ";after:forestry"// + + ";after:crafttweaker"// + + ";after:ic2"// + ; public static final String MODID = "buildcraftcompat"; public static final String VERSION = "$version"; public static final String GIT_BRANCH = "${git_branch}"; @@ -55,30 +50,48 @@ public class BCCompat { public static final String GIT_COMMIT_MSG = "${git_commit_msg}"; public static final String GIT_COMMIT_AUTHOR = "${git_commit_author}"; - @Mod.Instance(MODID) + // @Instance(MOD_ID) public static BCCompat instance; - private static final Map modules = new HashMap<>(); + private static final Map moduleConfigs = new HashMap<>(); - private static void offerAndPreInitModule(final CompatModuleBase module) { + public static Configuration config; + + public BCCompat() { + instance = this; + } + + private static void offerAndPreInitModule(CompatModuleBase module) { String cModId = module.compatModId(); if (module.canLoad()) { - Property prop = BCCoreConfig.config.get("modules", cModId, true); - if (prop.getBoolean(true)) { - modules.put(cModId, module); - BCLog.logger.info("[compat] + " + cModId); - module.preInit(); - } else { - BCLog.logger.info("[compat] x " + cModId + " (It has been disabled in the config)"); - } + String _modules = "modules"; + BooleanValue prop = config + .define(_modules, + "", + EnumRestartRequirement.NONE, + cModId, true); + modules.put(cModId, module); + moduleConfigs.put(cModId, prop); +// if (prop.get()) { +// modules.put(cModId, module); +// BCLog.logger.info("[compat] + " + cModId); +// module.preInit(); +// } else { +// BCLog.logger.info("[compat] x " + cModId + " (It has been disabled in the config)"); +// } } else { BCLog.logger.info("[compat] x " + cModId + " (It cannot load)"); } } - @Mod.EventHandler - public static void preInit(final FMLPreInitializationEvent evt) { + @SubscribeEvent + public static void preInit(FMLConstructModEvent evt) { + // Start config + BCModules module = BCModules.COMPAT; + ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder(); + config = new Configuration(builder, module); + // init BCLog.logger.info(""); BCLog.logger.info("Starting BuildCraftCompat " + VERSION); BCLog.logger.info("Copyright (c) the BuildCraft team, 2011-2017"); @@ -94,54 +107,48 @@ public static void preInit(final FMLPreInitializationEvent evt) { BCLog.logger.info("[compat] Module list:"); // List of all modules - offerAndPreInitModule(new CompatModuleForestry()); + // TODO Calen Forestry? +// offerAndPreInitModule(new CompatModuleForestry()); offerAndPreInitModule(new CompatModuleTheOneProbe()); offerAndPreInitModule(new CompatModuleCraftTweaker()); offerAndPreInitModule(new CompatModuleIndustrialCraft2()); // End of module list - } - @Mod.EventHandler - public static void init(final FMLInitializationEvent evt) { - NetworkRegistry.INSTANCE.registerGuiHandler(instance, CompatGui.guiHandlerProxy); - - // compatChannelHandler = new ChannelHandler(); - // MinecraftForge.EVENT_BUS.register(this); + // Finalize config + ForgeConfigSpec spec = config.build(); + ModContainer container = ModList.get().getModContainerById(module.getModId()).get(); + container.addConfig(new ModConfig(ModConfig.Type.COMMON, spec, container, config.getFileName())); + } - // compatChannelHandler.registerPacketType(PacketGenomeFilterChange.class); - // compatChannelHandler.registerPacketType(PacketTypeFilterChange.class); - // compatChannelHandler.registerPacketType(PacketRequestFilterSet.class); + /** This is called after config loaded. */ + private static void loadModules() { + modules.entrySet().forEach(entry -> + { + String cModId = entry.getKey(); + CompatModuleBase module = entry.getValue(); + if (moduleConfigs.get(cModId).get()) { + BCLog.logger.info("[compat] + " + cModId); + module.preInit(); + } else { + BCLog.logger.info("[compat] x " + cModId + " (It has been disabled in the config)"); + } + }); + } - for (final CompatModuleBase m : modules.values()) { + @SubscribeEvent + public static void init(FMLCommonSetupEvent evt) { + loadModules(); + // TODO Calen compat GUI??? +// NetworkRegistry.INSTANCE.registerGuiHandler(instance, CompatGui.guiHandlerProxy); + for (CompatModuleBase m : modules.values()) { m.init(); } } - @Mod.EventHandler - public static void postInit(final FMLPostInitializationEvent evt) { - for (final CompatModuleBase m : modules.values()) { + @SubscribeEvent + public static void postInit(FMLLoadCompleteEvent evt) { + for (CompatModuleBase m : modules.values()) { m.postInit(); } } - - // @Mod.EventHandler - // public void missingMapping(FMLMissingMappingsEvent event) { - // CompatModuleForestry.missingMapping(event); - // } - - // @SubscribeEvent - // @SideOnly(Side.CLIENT) - // public void handleTextureRemap(TextureStitchEvent.Pre event) { - // if (event.map.getTextureType() == 1) { - // TextureManager.getInstance().initIcons(event.map); - // } - // } - - // public static boolean isLoaded(String module) { - // return moduleNames.contains(module); - // } - - // public static boolean hasModule(final String module) { - // return BuildCraftCompat.moduleNames.contains(module); - // } } diff --git a/common/buildcraft/compat/CompatModuleBase.java b/common/buildcraft/compat/CompatModuleBase.java index 483f782..233b729 100644 --- a/common/buildcraft/compat/CompatModuleBase.java +++ b/common/buildcraft/compat/CompatModuleBase.java @@ -1,10 +1,11 @@ package buildcraft.compat; -import net.minecraftforge.fml.common.Loader; +import net.minecraftforge.fml.ModList; public abstract class CompatModuleBase { public boolean canLoad() { - return Loader.isModLoaded(this.compatModId()); +// return Loader.isModLoaded(this.compatModId()); + return ModList.get().isLoaded(this.compatModId()); } public abstract String compatModId(); diff --git a/common/buildcraft/compat/CompatUtils.java b/common/buildcraft/compat/CompatUtils.java index 876fd34..d103182 100644 --- a/common/buildcraft/compat/CompatUtils.java +++ b/common/buildcraft/compat/CompatUtils.java @@ -1,29 +1,22 @@ package buildcraft.compat; -import java.util.List; - +import buildcraft.api.core.CapabilitiesHelper; +import buildcraft.compat.network.IGuiCreator; +import buildcraft.lib.tile.item.ItemHandlerSimple; import com.google.common.collect.Lists; - import net.minecraft.item.ItemStack; - import net.minecraftforge.common.capabilities.Capability; -import buildcraft.api.core.CapabilitiesHelper; - -import buildcraft.lib.tile.item.ItemHandlerSimple; - -import buildcraft.compat.network.IGuiCreator; +import java.util.List; public class CompatUtils { + public static Capability CAP_GUI_CREATOR; - public static final Capability CAP_GUI_CREATOR = - CapabilitiesHelper.registerCapability(IGuiCreator.class); - - private CompatUtils() {} + private CompatUtils() { + } public static List compactInventory(ItemHandlerSimple inventory) { List stacks = Lists.newArrayList(); - for (int slot = 0; slot < inventory.getSlots(); slot++) { ItemStack stack = inventory.getStackInSlot(slot); if (stack.isEmpty()) { @@ -32,7 +25,7 @@ public static List compactInventory(ItemHandlerSimple inventory) { boolean handled = false; for (ItemStack existing : stacks) { - if (existing.isItemEqual(stack)) { + if (existing.sameItem(stack)) { existing.grow(stack.getCount()); handled = true; break; @@ -45,4 +38,8 @@ public static List compactInventory(ItemHandlerSimple inventory) { return stacks; } + + public static void regCaps() { + CAP_GUI_CREATOR = CapabilitiesHelper.registerCapability(IGuiCreator.class); + } } diff --git a/common/buildcraft/compat/module/crafttweaker/AssemblyTable.java b/common/buildcraft/compat/module/crafttweaker/AssemblyTable.java index a06e22c..8d2eb9c 100644 --- a/common/buildcraft/compat/module/crafttweaker/AssemblyTable.java +++ b/common/buildcraft/compat/module/crafttweaker/AssemblyTable.java @@ -1,105 +1,186 @@ package buildcraft.compat.module.crafttweaker; +import buildcraft.api.mj.MjAPI; +import buildcraft.api.recipes.IAssemblyRecipe; +import buildcraft.api.recipes.IngredientStack; +import buildcraft.lib.recipe.assembly.AssemblyRecipe; +import buildcraft.lib.recipe.assembly.AssemblyRecipeBasic; +import buildcraft.lib.recipe.assembly.IFacadeAssemblyRecipes; +import buildcraft.silicon.recipe.FacadeAssemblyRecipes; +import com.blamejared.crafttweaker.api.CraftTweakerAPI; +import com.blamejared.crafttweaker.api.annotations.ZenRegister; +import com.blamejared.crafttweaker.api.item.IIngredient; +import com.blamejared.crafttweaker.api.item.IItemStack; +import com.blamejared.crafttweaker.api.managers.IRecipeManager; +import com.blamejared.crafttweaker.api.recipes.IRecipeHandler; +import com.blamejared.crafttweaker.api.util.StringUtils; +import com.blamejared.crafttweaker.impl.actions.recipes.ActionAddRecipe; +import com.blamejared.crafttweaker.impl.actions.recipes.ActionRemoveRecipeByName; +import com.blamejared.crafttweaker.impl.helper.ItemStackHelper; import com.google.common.collect.ImmutableSet; -import com.google.common.collect.ImmutableSet.Builder; - +import com.google.common.collect.Lists; import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.IRecipeType; import net.minecraft.item.crafting.Ingredient; import net.minecraft.util.ResourceLocation; +import org.openzen.zencode.java.ZenCodeGlobals; +import org.openzen.zencode.java.ZenCodeType; -import buildcraft.api.mj.MjAPI; -import buildcraft.api.recipes.AssemblyRecipeBasic; -import buildcraft.api.recipes.IngredientStack; - -import buildcraft.lib.recipe.AssemblyRecipeRegistry; - -import crafttweaker.CraftTweakerAPI; -import crafttweaker.IAction; -import crafttweaker.annotations.ModOnly; -import crafttweaker.api.item.IIngredient; -import crafttweaker.api.item.IItemStack; -import crafttweaker.api.minecraft.CraftTweakerMC; -import stanhebben.zenscript.annotations.ZenClass; -import stanhebben.zenscript.annotations.ZenMethod; +import java.util.stream.Collectors; -@ZenClass("mods.buildcraft.AssemblyTable") -@ModOnly("buildcraftsilicon") -public class AssemblyTable { +//@ZenClass("mods.buildcraft.AssemblyTable") +//@ModOnly("buildcraftsilicon") +@ZenRegister +@ZenCodeType.Name("mods.buildcraft.AssemblyTable") +@IRecipeHandler.For(IAssemblyRecipe.class) +//public class AssemblyTable +public enum AssemblyTable implements IRecipeManager, IRecipeHandler { + @ZenCodeGlobals.Global("assemblyTable") + INSTANCE; private static int ids; - @ZenMethod - public static void addRecipe(IItemStack output, int power, IIngredient[] ingredients) { - addRecipe0("auto_" + ids++, output, power, ingredients); - } - - @ZenMethod - public static void addRecipe(String name, IItemStack output, int power, IIngredient[] ingredients) { +// // @ZenMethod +// @ZenCodeType.Method +// // public static void addRecipe(IItemStack output, int power, IIngredient[] ingredients) +// public void addRecipe(IItemStack output, int power, IIngredient[] ingredients) { +// addRecipe0("auto_" + ids++, output, power, ingredients); +// } + + // @ZenMethod + @ZenCodeType.Method +// public static void addRecipe(String name, IItemStack output, int power, IIngredient[] ingredients) + public void addRecipe(String name, IItemStack output, int power, IIngredient[] ingredients) { addRecipe0("custom/" + name, output, power, ingredients); } - private static void addRecipe0(String name, IItemStack output, int power, IIngredient[] ingredients) { - CraftTweakerAPI.apply(new AddRecipeAction(name, output, power, ingredients)); + // @ZenMethod + @ZenCodeType.Method +// public static void addRecipe(String name, IItemStack output, int power, IIngredient[] ingredients) + public void enableFacadeAssembly() { + enableFacadeAssembly0(); } - @ZenMethod - public static void removeByName(String name) { - CraftTweakerAPI.apply(new RemoveRecipeByNameAction(new ResourceLocation(name))); + // private static void addRecipe0(String name, IItemStack output, int power, IIngredient[] ingredients) + private void addRecipe0(String name, IItemStack output, int power, IIngredient[] ingredients) { +// CraftTweakerAPI.apply(new AddRecipeAction(name, output, power, ingredients)); + CraftTweakerAPI.apply(AddRecipeAction.create(this, name, output, power, ingredients)); } - // ###################### - // ### Action classes ### - // ###################### + // private static void addRecipe0(String name, IItemStack output, int power, IIngredient[] ingredients) + private void enableFacadeAssembly0() { +// CraftTweakerAPI.apply(new AddRecipeAction(name, output, power, ingredients)); + CraftTweakerAPI.apply(AddRecipeAction.createFacadeRecipe(this)); + } - private static class AddRecipeAction implements IAction { + // @ZenMethod + @ZenCodeType.Method + // public static void removeByName(String name) + public void removeByName(String name) { +// CraftTweakerAPI.apply(new RemoveRecipeByNameAction(new ResourceLocation(name))); + CraftTweakerAPI.apply(new RemoveRecipeByNameAction(this, new ResourceLocation(name))); + } - private final ItemStack output; - private final ResourceLocation name; - private final long requiredMj; - private final ImmutableSet requiredStacks; + @Override + public IRecipeType getRecipeType() { + return IAssemblyRecipe.TYPE; + } - public AddRecipeAction(String name, IItemStack output, int power, IIngredient[] ingredients) { - this.output = CraftTweakerMC.getItemStack(output); + @Override + public String dumpToCommandString(final IRecipeManager manager, IAssemblyRecipe recipe) { + if (recipe instanceof IFacadeAssemblyRecipes) { + return String.format( + "assemblyTable.enableFacadeAssembly();" + ); + } else { + return String.format( + "assemblyTable.addRecipe(%s, %s, %s, %s);", + StringUtils.quoteAndEscape(recipe.getId()), + ItemStackHelper.getCommandString(Lists.newArrayList(recipe.getOutputPreviews()).get(0)), + recipe.getRequiredMicroJoules(), + recipe.getRequiredIngredientStacks().stream() + .map(i -> IIngredient.fromIngredient(i.ingredient)) + .map(IIngredient::getCommandString) + .collect(Collectors.joining(", ", "[", "]")) + ); + } + } - Builder stacks = ImmutableSet.builder(); - for (int i = 0; i < ingredients.length; i++) { - IIngredient ctIng = ingredients[i]; - Ingredient ingredient = CraftTweakerMC.getIngredient(ctIng); - stacks.add(new IngredientStack(ingredient, Math.max(1, ctIng.getAmount()))); - } - requiredStacks = stacks.build(); + // private static class RemoveRecipeByNameAction implements IAction + private static class RemoveRecipeByNameAction extends ActionRemoveRecipeByName { + private final ResourceLocation name; - this.requiredMj = power * MjAPI.MJ; - this.name = new ResourceLocation("crafttweaker", name); + // RemoveRecipeByNameAction(ResourceLocation name) + RemoveRecipeByNameAction(IRecipeManager manager, ResourceLocation name) { + super(manager, name); + this.name = name; } - @Override public void apply() { - AssemblyRecipeRegistry.REGISTRY.put(name, - new AssemblyRecipeBasic(name, requiredMj, requiredStacks, output)); +// AssemblyRecipeRegistry.REGISTRY.remove(this.name); + getManager().removeByName(this.name.toString()); } - @Override public String describe() { - return "Adding assembly table recipe for " + output; + return "Removing assembly table recipe " + this.name; } } - private static class RemoveRecipeByNameAction implements IAction { - private final ResourceLocation name; + // private static class AddRecipeAction implements IAction + private static class AddRecipeAction extends ActionAddRecipe { +// private final ItemStack output; +// private final ResourceLocation name; +// private final long requiredMj; +// private final ImmutableSet requiredStacks; + + // public AddRecipeAction(IRecipeManager manager, String name, IItemStack output, int power, IIngredient[] ingredients) + private AddRecipeAction(IRecipeManager manager, AssemblyRecipe recipe) { + super(manager, recipe); +// this.output = CraftTweakerMC.getItemStack(output); +// ImmutableSet.Builder stacks = ImmutableSet.builder(); +// +// for (int i = 0; i < ingredients.length; ++i) { +// IIngredient ctIng = ingredients[i]; +// Ingredient ingredient = CraftTweakerMC.getIngredient(ctIng); +// stacks.add(new IngredientStack(ingredient, Math.max(1, ctIng.getAmount()))); +// } +// +// this.requiredStacks = stacks.build(); +// this.requiredMj = (long) power * MjAPI.MJ; +// this.name = new ResourceLocation("crafttweaker", name); + } - RemoveRecipeByNameAction(ResourceLocation name) { - this.name = name; + public static AddRecipeAction create(IRecipeManager manager, String name, IItemStack output, int power, IIngredient[] ingredients) { +// ItemStack output = CraftTweakerMC.getItemStack(output); + ItemStack _output = output.getImmutableInternal(); + ImmutableSet.Builder stacks = ImmutableSet.builder(); + + for (int i = 0; i < ingredients.length; ++i) { + IIngredient ctIng = ingredients[i]; +// Ingredient ingredient = CraftTweakerMC.getIngredient(ctIng); + Ingredient ingredient = ctIng.asVanillaIngredient(); +// stacks.add(new IngredientStack(ingredient, Math.max(1, ctIng.getAmount()))); + stacks.add(new IngredientStack(ingredient, Math.max(1, Lists.newArrayList(ctIng.getItems()).stream().findAny().map(IItemStack::getAmount).orElse(1)))); + } + + ImmutableSet requiredStacks = stacks.build(); + long requiredMj = (long) power * MjAPI.MJ; + ResourceLocation _name = new ResourceLocation("crafttweaker", name); + AssemblyRecipeBasic recipe = new AssemblyRecipeBasic(_name, requiredMj, requiredStacks, _output); + return new AddRecipeAction(manager, recipe); } - @Override - public void apply() { - AssemblyRecipeRegistry.REGISTRY.remove(name); + public static AddRecipeAction createFacadeRecipe(IRecipeManager manager) { + return new AddRecipeAction(manager, FacadeAssemblyRecipes.INSTANCE); } - @Override +// public void apply() { +// AssemblyRecipeRegistry.REGISTRY.put(this.name, new AssemblyRecipeBasic(this.name, this.requiredMj, this.requiredStacks, this.output)); +// } + public String describe() { - return "Removing assembly table recipe " + name; +// return "Adding assembly table recipe for " + this.output; + return "Adding assembly table recipe for " + Lists.newArrayList(((IAssemblyRecipe) this.recipe).getOutputPreviews()).get(0); } } } diff --git a/common/buildcraft/compat/module/crafttweaker/CombustionEngine.java b/common/buildcraft/compat/module/crafttweaker/CombustionEngine.java index f1cb66a..2a60ddb 100644 --- a/common/buildcraft/compat/module/crafttweaker/CombustionEngine.java +++ b/common/buildcraft/compat/module/crafttweaker/CombustionEngine.java @@ -1,153 +1,199 @@ package buildcraft.compat.module.crafttweaker; -import net.minecraftforge.fluids.FluidStack; - -import buildcraft.api.fuels.BuildcraftFuelRegistry; +import buildcraft.api.fuels.IFluidCoolant; +import buildcraft.api.fuels.IFuel; +import buildcraft.api.fuels.IFuelManager; import buildcraft.api.mj.MjAPI; +import buildcraft.lib.recipe.fuel.FuelRegistry; +import com.blamejared.crafttweaker.api.CraftTweakerAPI; +import com.blamejared.crafttweaker.api.annotations.ZenRegister; +import com.blamejared.crafttweaker.api.fluid.IFluidStack; +import com.blamejared.crafttweaker.api.managers.IRecipeManager; +import com.blamejared.crafttweaker.api.recipes.IRecipeHandler; +import com.blamejared.crafttweaker.api.util.StringUtils; +import com.blamejared.crafttweaker.impl.actions.recipes.ActionAddRecipe; +import net.minecraft.fluid.EmptyFluid; +import net.minecraft.item.crafting.IRecipeType; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fluids.FluidStack; +import org.openzen.zencode.java.ZenCodeGlobals; +import org.openzen.zencode.java.ZenCodeType; -import buildcraft.lib.engine.TileEngineBase_BC8; - -import crafttweaker.CraftTweakerAPI; -import crafttweaker.IAction; -import crafttweaker.annotations.ModOnly; -import crafttweaker.api.liquid.ILiquidStack; -import crafttweaker.api.minecraft.CraftTweakerMC; -import stanhebben.zenscript.annotations.ZenClass; -import stanhebben.zenscript.annotations.ZenMethod; +//@ZenClass("mods.buildcraft.CombustionEngine") +//@ModOnly("buildcraftenergy") +@ZenRegister +@ZenCodeType.Name("mods.buildcraft.CombustionEngine") +@IRecipeHandler.For(IFuel.class) +//public class CombustionEngine +public enum CombustionEngine implements IRecipeManager, IRecipeHandler { + @ZenCodeGlobals.Global("combustionEngine") + INSTANCE; -@ZenClass("mods.buildcraft.CombustionEngine") -@ModOnly("buildcraftenergy") -public class CombustionEngine { + private static final double MAX_POWER = 100000.0; - private static final double MAX_POWER - = (TileEngineBase_BC8.MAX_HEAT - TileEngineBase_BC8.MIN_HEAT) / TileEngineBase_BC8.HEAT_PER_MJ; + // @ZenMethod + @ZenCodeType.Method + public void addCleanFuel(String name, IFluidStack liquid, double powerPerTick, int timePerBucket) { + addCleanFuel0("custom/" + name, liquid, powerPerTick, timePerBucket); + } - @ZenMethod - public static void addCleanFuel(ILiquidStack liquid, double powerPerTick, int timePerBucket) { - FluidStack fluid = CraftTweakerMC.getLiquidStack(liquid); - if (fluid == null) { - throw new IllegalArgumentException("Fluid was null!"); - } - if (BuildcraftFuelRegistry.fuel.getFuel(fluid) != null) { + // @ZenMethod + // @ZenCodeType.Method + // public static void addCleanFuel(ILiquidStack liquid, double powerPerTick, int timePerBucket) + private void addCleanFuel0(String name, IFluidStack liquid, double powerPerTick, int timePerBucket) { +// FluidStack fluid = CraftTweakerMC.getLiquidStack(liquid); + FluidStack fluid = liquid.getImmutableInternal(); +// if (fluid == null) + if (fluid.getFluid() == null || fluid.getFluid() instanceof EmptyFluid) { + throw new IllegalArgumentException("Fluid was null or empty!"); + } +// else if (BuildcraftFuelRegistry.fuel.getFuel(fluid) != null) + else if (getAllRecipes().stream().anyMatch(r -> ((IFuel) r.getRecipe()).getFluid().equals(fluid))) { throw new IllegalArgumentException("The fluid " + fluid + " is already registered as a fuel!"); } - if (BuildcraftFuelRegistry.coolant.getCoolant(fluid) != null) { - throw new IllegalArgumentException( - "The fluid " + fluid - + " is already registered as a coolant - so it won't work very well if you add it as a fuel too!" - ); - } - if (powerPerTick <= 0) { +// else if (BuildcraftFuelRegistry.coolant.getCoolant(fluid) != null) + else if (Coolant.INSTANCE.getAllRecipes().stream().anyMatch(r -> r.getRecipe() instanceof IFluidCoolant && ((IFluidCoolant) r.getRecipe()).getFluid().equals(fluid))) { + throw new IllegalArgumentException("The fluid " + fluid + " is already registered as a coolant - so it won't work very well if you add it as a fuel too!"); + } else if (powerPerTick <= 0.0) { throw new IllegalArgumentException("Power was less than or equal to 0!"); + } else if (powerPerTick > 100000.0) { + throw new IllegalArgumentException("Maximum power is 100000.0, as any values above this would instantly bring the engine to overheat."); + } else { + long mj = (long) ((double) MjAPI.MJ * powerPerTick); +// CraftTweakerAPI.apply(new AddCleanFuel(fluid, mj, timePerBucket)); + CraftTweakerAPI.apply(AddCleanFuel.create(this, name, fluid, mj, timePerBucket)); } - if (powerPerTick > MAX_POWER) { - throw new IllegalArgumentException( - "Maximum power is " + MAX_POWER - + ", as any values above this would instantly bring the engine to overheat." - ); - } - long mj = (long) (MjAPI.MJ * powerPerTick); - CraftTweakerAPI.apply(new AddCleanFuel(fluid, mj, timePerBucket)); } - @ZenMethod - public static void addDirtyFuel(ILiquidStack lFuel, double powerPerTick, int timePerBucket, ILiquidStack lResidue) { - FluidStack fuel = CraftTweakerMC.getLiquidStack(lFuel); - FluidStack residue = CraftTweakerMC.getLiquidStack(lResidue); - if (fuel.getFluid() == null) { - throw new IllegalArgumentException("Fuel fluid was null!"); - } - if (residue.getFluid() == null) { - throw new IllegalArgumentException("Residue fluid was null!"); - } - if (BuildcraftFuelRegistry.fuel.getFuel(fuel) != null) { + // @ZenMethod + @ZenCodeType.Method + public void addDirtyFuel(String name, IFluidStack lFuel, double powerPerTick, int timePerBucket, IFluidStack lResidue) { + addDirtyFuel0("custom/" + name, lFuel, powerPerTick, timePerBucket, lResidue); + } + + // @ZenMethod + // @ZenCodeType.Method + // public static void addDirtyFuel(ILiquidStack lFuel, double powerPerTick, int timePerBucket, ILiquidStack lResidue) + private void addDirtyFuel0(String name, IFluidStack lFuel, double powerPerTick, int timePerBucket, IFluidStack lResidue) { +// FluidStack fuel = CraftTweakerMC.getLiquidStack(lFuel); + FluidStack fuel = lFuel.getImmutableInternal(); +// FluidStack residue = CraftTweakerMC.getLiquidStack(lResidue); + FluidStack residue = lResidue.getImmutableInternal(); +// if (fuel.getFluid() == null) + if (fuel.getFluid() == null || fuel.getFluid() instanceof EmptyFluid) { +// throw new IllegalArgumentException("Fuel fluid was null!"); + throw new IllegalArgumentException("Fuel fluid was null or empty!"); + } +// else if (residue.getFluid() == null) + else if (residue.getFluid() == null || residue.getFluid() instanceof EmptyFluid) { +// throw new IllegalArgumentException("Residue fluid was null!"); + throw new IllegalArgumentException("Residue fluid was null or empty!"); + } +// else if (BuildcraftFuelRegistry.fuel.getFuel(fuel) != null) + else if (getAllRecipes().stream().anyMatch(r -> ((IFuel) r.getRecipe()).getFluid().equals(fuel))) { throw new IllegalArgumentException("The fluid " + fuel + " is already registered as a fuel!"); } - if (BuildcraftFuelRegistry.coolant.getCoolant(fuel) != null) { - throw new IllegalArgumentException( - "The fluid " + fuel - + " is already registered as a coolant - so it won't work very well if you add it as a fuel too!" - ); - } - if (powerPerTick <= 0) { +// else if (BuildcraftFuelRegistry.coolant.getCoolant(fuel) != null) + else if (Coolant.INSTANCE.getAllRecipes().stream().anyMatch(r -> r.getRecipe() instanceof IFluidCoolant && ((IFluidCoolant) r.getRecipe()).getFluid().equals(fuel))) { + throw new IllegalArgumentException("The fluid " + fuel + " is already registered as a coolant - so it won't work very well if you add it as a fuel too!"); + } else if (powerPerTick <= 0.0) { throw new IllegalArgumentException("Power was less than or equal to 0!"); + } else if (powerPerTick > 100000.0) { + throw new IllegalArgumentException("Maximum power is 100000.0, as any values above this would instantly bring the engine to overheat."); + } else { + long mj = (long) ((double) MjAPI.MJ * powerPerTick); +// CraftTweakerAPI.apply(new AddDirtyFuel(fuel, mj, timePerBucket, residue)); + CraftTweakerAPI.apply(AddDirtyFuel.create(this, name, fuel, mj, timePerBucket, residue)); } - if (powerPerTick > MAX_POWER) { - throw new IllegalArgumentException( - "Maximum power is " + MAX_POWER - + ", as any values above this would instantly bring the engine to overheat." - ); - } - long mj = (long) (MjAPI.MJ * powerPerTick); - CraftTweakerAPI.apply(new AddDirtyFuel(fuel, mj, timePerBucket, residue)); } - // @ZenMethod - // public static void addLiquidCoolant(FluidStack coolant) { - // - // } - // - // @ZenMethod - // public static void addSolidCoolant(ItemStack stack, FluidStack coolant) { - // - // } - - // ###################### - // ### Action classes ### - // ###################### + @Override + public IRecipeType getRecipeType() { + return IFuel.TYPE; + } - static final class AddCleanFuel implements IAction { + @Override + public String dumpToCommandString(final IRecipeManager manager, IFuel recipe) { + if (recipe instanceof IFuelManager.IDirtyFuel) { + IFuelManager.IDirtyFuel dirtyFuel = (IFuelManager.IDirtyFuel) recipe; + return String.format( + "combustionEngine.addDirtyFuel(%s, %s, %s, %s, %s);", + StringUtils.quoteAndEscape(recipe.getId()), + StringUtils.quoteAndEscape(recipe.getFluid().getFluid().getRegistryName()), + recipe.getPowerPerCycle(), + recipe.getTotalBurningTime(), + StringUtils.quoteAndEscape(dirtyFuel.getResidue().getFluid().getRegistryName()) + ); + } else { + return String.format( + "combustionEngine.addCleanFuel(%s, %s, %s, %s);", + StringUtils.quoteAndEscape(recipe.getId()), + StringUtils.quoteAndEscape(recipe.getFluid().getFluid().getRegistryName()), + recipe.getPowerPerCycle(), + recipe.getTotalBurningTime() + ); + } + } - private final FluidStack fluid; - private final long powerPerTick; - private final int totalBurningTime; + // static final class AddDirtyFuel implements IAction + static final class AddDirtyFuel extends ActionAddRecipe { +// private final FluidStack fuel; +// private final FluidStack residue; +// private final long powerPerTick; +// private final int totalBurningTime; - public AddCleanFuel(FluidStack fluid, long powerPerCycle, int totalBurningTime) { - this.fluid = fluid; - this.powerPerTick = powerPerCycle; - this.totalBurningTime = totalBurningTime; + // public AddDirtyFuel(FluidStack fuel, long powerPerCycle, int totalBurningTime, FluidStack residue) + private AddDirtyFuel(IRecipeManager manager, IFuel recipe) { + super(manager, recipe); +// this.fuel = fuel; +// this.powerPerTick = powerPerCycle; +// this.totalBurningTime = totalBurningTime; +// this.residue = residue; } - @Override - public void apply() { - BuildcraftFuelRegistry.fuel.addFuel(fluid, powerPerTick, totalBurningTime); + // Calen + public static AddDirtyFuel create(IRecipeManager manager, String name, FluidStack fuel, long powerPerCycle, int totalBurningTime, FluidStack residue) { + ResourceLocation _name = new ResourceLocation("crafttweaker", name); + return new AddDirtyFuel(manager, new FuelRegistry.DirtyFuel(_name, fuel, powerPerCycle, totalBurningTime, residue)); } - @Override +// public void apply() { +// BuildcraftFuelRegistry.fuel.addDirtyFuel(this.fuel, this.powerPerTick, this.totalBurningTime, this.residue); +// } + public String describe() { - return "Adding combustion engine fuel " + fluid; +// return "Adding combustion engine fuel " + this.fuel; + return "Adding combustion engine fuel " + ((IFuel) this.recipe).getFluid(); } } - static final class AddDirtyFuel implements IAction { - - private final FluidStack fuel, residue; - private final long powerPerTick; - private final int totalBurningTime; + // static final class AddCleanFuel implements IAction + static final class AddCleanFuel extends ActionAddRecipe { +// private final FluidStack fluid; +// private final long powerPerTick; +// private final int totalBurningTime; - public AddDirtyFuel(FluidStack fuel, long powerPerCycle, int totalBurningTime, FluidStack residue) { - this.fuel = fuel; - this.powerPerTick = powerPerCycle; - this.totalBurningTime = totalBurningTime; - this.residue = residue; + // public AddCleanFuel(FluidStack fluid, long powerPerCycle, int totalBurningTime) + public AddCleanFuel(IRecipeManager manager, IFuel recipe) { + super(manager, recipe); +// this.fluid = fluid; +// this.powerPerTick = powerPerCycle; +// this.totalBurningTime = totalBurningTime; } - @Override - public void apply() { - BuildcraftFuelRegistry.fuel.addDirtyFuel(fuel, powerPerTick, totalBurningTime, residue); + // Calen + public static AddCleanFuel create(IRecipeManager manager, String name, FluidStack fluid, long powerPerCycle, int totalBurningTime) { + ResourceLocation _name = new ResourceLocation("crafttweaker", name); + return new AddCleanFuel(manager, new FuelRegistry.Fuel(_name, fluid, powerPerCycle, totalBurningTime)); } - @Override +// public void apply() { +// BuildcraftFuelRegistry.fuel.addFuel(this.fluid, this.powerPerTick, this.totalBurningTime); +// } + public String describe() { - return "Adding combustion engine fuel " + fuel; +// return "Adding combustion engine fuel " + this.fluid; + return "Adding combustion engine fuel " + ((IFuel) this.recipe).getFluid(); } } - - // static final class AddLiquidCoolant implements IAction { - // - // } - // - // static final class AddSolidCoolant implements IAction { - // - // } } diff --git a/common/buildcraft/compat/module/crafttweaker/CompatModuleCraftTweaker.java b/common/buildcraft/compat/module/crafttweaker/CompatModuleCraftTweaker.java index 7e93009..1f43709 100644 --- a/common/buildcraft/compat/module/crafttweaker/CompatModuleCraftTweaker.java +++ b/common/buildcraft/compat/module/crafttweaker/CompatModuleCraftTweaker.java @@ -2,17 +2,17 @@ import buildcraft.compat.CompatModuleBase; -import crafttweaker.CraftTweakerAPI; - public class CompatModuleCraftTweaker extends CompatModuleBase { - @Override + public CompatModuleCraftTweaker() { + } + public String compatModId() { return "crafttweaker"; } - @Override public void preInit() { - CraftTweakerAPI.registerClass(AssemblyTable.class); - CraftTweakerAPI.registerClass(CombustionEngine.class); +// CraftTweakerAPI.registerClass(AssemblyTable.class); +// CraftTweakerAPI.getRegistry()..registerClass(AssemblyTable.class); +// CraftTweakerAPI.registerClass(CombustionEngine.class); } } diff --git a/common/buildcraft/compat/module/crafttweaker/Coolant.java b/common/buildcraft/compat/module/crafttweaker/Coolant.java new file mode 100644 index 0000000..972b3a9 --- /dev/null +++ b/common/buildcraft/compat/module/crafttweaker/Coolant.java @@ -0,0 +1,132 @@ +package buildcraft.compat.module.crafttweaker; + +import buildcraft.api.fuels.ICoolant; +import buildcraft.api.fuels.IFluidCoolant; +import buildcraft.api.fuels.IFuel; +import buildcraft.api.fuels.ISolidCoolant; +import buildcraft.lib.recipe.coolant.CoolantRegistry; +import com.blamejared.crafttweaker.api.CraftTweakerAPI; +import com.blamejared.crafttweaker.api.annotations.ZenRegister; +import com.blamejared.crafttweaker.api.fluid.IFluidStack; +import com.blamejared.crafttweaker.api.item.IItemStack; +import com.blamejared.crafttweaker.api.managers.IRecipeManager; +import com.blamejared.crafttweaker.api.recipes.IRecipeHandler; +import com.blamejared.crafttweaker.api.util.StringUtils; +import com.blamejared.crafttweaker.impl.actions.recipes.ActionAddRecipe; +import com.blamejared.crafttweaker.impl.helper.ItemStackHelper; +import net.minecraft.fluid.EmptyFluid; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.item.crafting.IRecipeType; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fluids.FluidStack; +import org.openzen.zencode.java.ZenCodeGlobals; +import org.openzen.zencode.java.ZenCodeType; + +@ZenRegister +@ZenCodeType.Name("mods.buildcraft.Coolant") +@IRecipeHandler.For(ICoolant.class) +public enum Coolant implements IRecipeManager, IRecipeHandler { + @ZenCodeGlobals.Global("coolant") + INSTANCE; + + @ZenCodeType.Method + public void addFluidCoolant(String name, IFluidStack liquid, float degreesCoolingPerMB) { + addFluidCoolant0("custom/" + name, liquid, degreesCoolingPerMB); + } + + private void addFluidCoolant0(String name, IFluidStack liquid, float degreesCoolingPerMB) { + FluidStack fluid = liquid.getImmutableInternal(); + if (fluid == null) { + throw new IllegalArgumentException("Fluid was null!"); + } else if (getAllRecipes().stream().anyMatch(r -> r.getRecipe() instanceof IFluidCoolant && ((IFluidCoolant) r.getRecipe()).getFluid().equals(fluid))) { + throw new IllegalArgumentException("The fluid " + fluid + " is already registered as a coolant!"); + } else if (CombustionEngine.INSTANCE.getAllRecipes().stream().anyMatch(r -> ((IFuel) r.getRecipe()).getFluid().equals(fluid))) { + throw new IllegalArgumentException("The fluid " + fluid + " is already registered as a fuel - so it won't work very well if you add it as a coolant too!"); + } else if (degreesCoolingPerMB <= 0.0) { + throw new IllegalArgumentException("Degrees cooling per MB was less than or equal to 0!"); + } else { + CraftTweakerAPI.apply(AddFluidCoolant.create(this, name, fluid, degreesCoolingPerMB)); + } + } + + // @ZenMethod + @ZenCodeType.Method + public void addSolidCoolant(String name, IItemStack item, IFluidStack lFuel, float multiplier) { + addSolidCoolant0("custom/" + name, item, lFuel, multiplier); + } + + private void addSolidCoolant0(String name, IItemStack itemIn, IFluidStack fluidIn, float multiplier) { + ItemStack item = itemIn.getImmutableInternal(); + FluidStack fluid = fluidIn.getImmutableInternal(); + if (item.getItem() == Items.AIR) { + throw new IllegalArgumentException("Coolant item was air!"); + } else if (fluid.getFluid() == null || fluid.getFluid() instanceof EmptyFluid) { + throw new IllegalArgumentException("Fluid was null or empty!"); + } else if (getAllRecipes().stream().anyMatch(r -> r.getRecipe() instanceof ISolidCoolant && ((ISolidCoolant) r.getRecipe()).getSolid().equals(item))) { + throw new IllegalArgumentException("The item " + item + " is already registered as a coolant!"); + } else if (multiplier <= 0.0) { + throw new IllegalArgumentException("Multiplier was less than or equal to 0!"); + } else { + CraftTweakerAPI.apply(AddSolidCoolant.create(this, name, item, fluid, multiplier)); + } + } + + @Override + public IRecipeType getRecipeType() { + return ICoolant.TYPE; + } + + @Override + public String dumpToCommandString(final IRecipeManager manager, ICoolant recipe) { + if (recipe instanceof IFluidCoolant) { + IFluidCoolant fluidCoolant = (IFluidCoolant) recipe; + return String.format( + "coolant.addFluidCoolant(%s, %s, %s);", + StringUtils.quoteAndEscape(recipe.getId()), + StringUtils.quoteAndEscape(recipe.getFluid().getFluid().getRegistryName()), + fluidCoolant.getDegreesCoolingPerMB() + ); + } else if (recipe instanceof ISolidCoolant) { + ISolidCoolant solidCoolant = (ISolidCoolant) recipe; + return String.format( + "coolant.addSolidCoolant(%s, %s, %s, %s);", + StringUtils.quoteAndEscape(recipe.getId()), + ItemStackHelper.getCommandString(solidCoolant.getSolid()), + StringUtils.quoteAndEscape(recipe.getFluid().getFluid().getRegistryName()), + solidCoolant.getMultiplier() + ); + } + return "This is not a fluid coolant or a solid coolant. What happened?"; + } + + static final class AddFluidCoolant extends ActionAddRecipe { + private AddFluidCoolant(IRecipeManager manager, IFluidCoolant recipe) { + super(manager, recipe); + } + + public static AddFluidCoolant create(IRecipeManager manager, String name, FluidStack fluid, float degreesCoolingPerMB) { + ResourceLocation _name = new ResourceLocation("crafttweaker", name); + return new AddFluidCoolant(manager, new CoolantRegistry.FluidCoolant(_name, fluid, degreesCoolingPerMB)); + } + + public String describe() { + return "Adding combustion engine coolant " + ((ICoolant) this.recipe).getFluid(); + } + } + + static final class AddSolidCoolant extends ActionAddRecipe { + public AddSolidCoolant(IRecipeManager manager, ISolidCoolant recipe) { + super(manager, recipe); + } + + public static AddSolidCoolant create(IRecipeManager manager, String name, ItemStack item, FluidStack fluid, float multiplier) { + ResourceLocation _name = new ResourceLocation("crafttweaker", name); + return new AddSolidCoolant(manager, new CoolantRegistry.SolidCoolant(_name, item, fluid, multiplier)); + } + + public String describe() { + return "Adding combustion engine coolant " + ((ISolidCoolant) this.recipe).getSolid(); + } + } +} diff --git a/common/buildcraft/compat/module/forestry/CompatModuleForestry.java b/common/buildcraft/compat/module/forestry/CompatModuleForestry.java deleted file mode 100644 index 622aca4..0000000 --- a/common/buildcraft/compat/module/forestry/CompatModuleForestry.java +++ /dev/null @@ -1,39 +0,0 @@ -package buildcraft.compat.module.forestry; - -import buildcraft.api.BCModules; -import buildcraft.api.core.BCLog; -import buildcraft.api.lists.ListRegistry; - -import buildcraft.compat.CompatModuleBase; -import buildcraft.compat.module.forestry.list.ListMatchGenome; -import buildcraft.compat.module.forestry.pipe.ForestryPipes; - -public class CompatModuleForestry extends CompatModuleBase { - @Override - public String compatModId() { - return "forestry"; - } - - @Override - public void preInit() { - ListRegistry.registerHandler(new ListMatchGenome()); - if (canLoadPropolisPipe()) { - ForestryPipes.preInit(); - } - } - - private static boolean canLoadPropolisPipe() { - if (!BCModules.TRANSPORT.isLoaded()) { - return false; - } - try { - // Ensure that forestry is up-to-date - Class.forName("forestry.sorting.tiles.IFilterContainer"); - return true; - } catch (ClassNotFoundException ignored) { - BCLog.logger.warn( - "[compat.forestry] IFilterContainer not found -- forestry must be updated to add the propolis pipe!"); - return false; - } - } -} diff --git a/common/buildcraft/compat/module/forestry/list/ListMatchGenome.java b/common/buildcraft/compat/module/forestry/list/ListMatchGenome.java deleted file mode 100644 index 7b9e247..0000000 --- a/common/buildcraft/compat/module/forestry/list/ListMatchGenome.java +++ /dev/null @@ -1,93 +0,0 @@ -package buildcraft.compat.module.forestry.list; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import net.minecraft.item.ItemStack; -import net.minecraft.util.NonNullList; - -import buildcraft.api.lists.ListMatchHandler; - -import forestry.api.genetics.AlleleManager; -import forestry.api.genetics.IAlleleSpecies; -import forestry.api.genetics.IIndividual; -import forestry.api.genetics.ISpeciesRoot; - -public class ListMatchGenome extends ListMatchHandler { - - @Override - public boolean matches(Type type, ItemStack compare, ItemStack target, boolean precise) { - IIndividual infoCompare = AlleleManager.alleleRegistry.getIndividual(compare); - IIndividual infoTarget = AlleleManager.alleleRegistry.getIndividual(target); - if (infoCompare == null || infoTarget == null) { - return false; - } - switch (type) { - case MATERIAL: { - return matchesMaterial(compare, target, infoCompare, infoTarget, precise); - } - case TYPE: { - return matchesType(compare, target, infoCompare, infoTarget, precise); - } - case CLASS: { - return matchesMaterial(compare, target, infoCompare, infoTarget, precise) - && matchesType(compare, target, infoCompare, infoTarget, precise); - } - default: { - throw new IllegalArgumentException("Unknown type " + type); - } - } - } - - private static boolean matchesMaterial(ItemStack compare, ItemStack target, IIndividual infoCompare, - IIndividual infoTarget, boolean precise) { - // Ensures that both individuals have the same species - // If precise is true then also ensure that the secondary species is the same - IAlleleSpecies speciesCompare = infoCompare.getGenome().getPrimary(); - IAlleleSpecies speciesTarget = infoTarget.getGenome().getPrimary(); - if (speciesCompare != speciesTarget) { - return false; - } - if (precise) { - IAlleleSpecies inactiveCompare = infoCompare.getGenome().getSecondary(); - IAlleleSpecies inactiveTarget = infoTarget.getGenome().getSecondary(); - if (inactiveCompare != inactiveTarget) { - return false; - } - } - return true; - } - - private static boolean matchesType(ItemStack compare, ItemStack target, IIndividual infoCompare, - IIndividual infoTarget, boolean precise) { - ISpeciesRoot speciesRootCompare = infoCompare.getGenome().getSpeciesRoot(); - ISpeciesRoot speciesRootTarget = infoTarget.getGenome().getSpeciesRoot(); - if (speciesRootCompare != speciesRootTarget) { - return false; - } - // Ensure that both fully match (both princesses or both drones etc) - if (speciesRootCompare.getType(compare) != speciesRootTarget.getType(target)) { - return false; - } - return true; - } - - @Override - public boolean isValidSource(Type type, @Nonnull ItemStack stack) { - return AlleleManager.alleleRegistry.getIndividual(stack) != null; - } - - @Override - @Nullable - public NonNullList getClientExamples(Type type, @Nonnull ItemStack stack) { - IIndividual individual = AlleleManager.alleleRegistry.getIndividual(stack); - if (individual == null) { - return null; - } - - NonNullList list = NonNullList.create(); - boolean isType = type != Type.MATERIAL; - boolean isMaterial = type != Type.TYPE; - return list; - } -} diff --git a/common/buildcraft/compat/module/forestry/pipe/ContainerPropolisPipe.java b/common/buildcraft/compat/module/forestry/pipe/ContainerPropolisPipe.java deleted file mode 100644 index 1460eff..0000000 --- a/common/buildcraft/compat/module/forestry/pipe/ContainerPropolisPipe.java +++ /dev/null @@ -1,22 +0,0 @@ -package buildcraft.compat.module.forestry.pipe; - -import net.minecraft.entity.player.EntityPlayer; - -import forestry.sorting.gui.ContainerGeneticFilter; - -public class ContainerPropolisPipe extends ContainerGeneticFilter { - - public final PipeBehaviourPropolis pipeBehaviour; - - public ContainerPropolisPipe(PipeBehaviourPropolis behaviour, EntityPlayer player) { - super(behaviour, player.inventory); - this.pipeBehaviour = behaviour; - behaviour.pipe.getHolder().onPlayerOpen(player); - } - - @Override - public void onContainerClosed(EntityPlayer player) { - super.onContainerClosed(player); - pipeBehaviour.pipe.getHolder().onPlayerClose(player); - } -} diff --git a/common/buildcraft/compat/module/forestry/pipe/ForestryPipes.java b/common/buildcraft/compat/module/forestry/pipe/ForestryPipes.java deleted file mode 100644 index cab9d26..0000000 --- a/common/buildcraft/compat/module/forestry/pipe/ForestryPipes.java +++ /dev/null @@ -1,86 +0,0 @@ -package buildcraft.compat.module.forestry.pipe; - -import net.minecraft.init.Items; -import net.minecraft.item.EnumDyeColor; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.item.crafting.IRecipe; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.ResourceLocation; - -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.RegistryEvent; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.common.registry.ForgeRegistries; -import net.minecraftforge.oredict.ShapedOreRecipe; - -import buildcraft.api.transport.pipe.PipeApi; -import buildcraft.api.transport.pipe.PipeDefinition; -import buildcraft.api.transport.pipe.PipeDefinition.PipeDefinitionBuilder; - -import buildcraft.lib.misc.ColourUtil; -import buildcraft.lib.registry.CreativeTabManager; - -public class ForestryPipes { - - public static Item pipeItemPropolis; - public static PipeDefinition pipeDefinitionPropolis; - - public static void preInit() { - MinecraftForge.EVENT_BUS.register(ForestryPipes.class); - - String[] textureSuffixes = new String[8]; - textureSuffixes[0] = ""; - textureSuffixes[7] = "_itemstack"; - for (EnumFacing face : EnumFacing.VALUES) { - textureSuffixes[face.ordinal() + 1] = "_" + face.getName(); - } - - pipeDefinitionPropolis = new PipeDefinitionBuilder()// - .id("forestry_propolis")// Note: id() automatically sets the namespace to "buildcraftcompat" - .texPrefix("propolis")// - .texSuffixes(textureSuffixes)// - .logic(PipeBehaviourPropolis::new, PipeBehaviourPropolis::new)// - .flowItem()// - .define(); - - PipeApi.pipeRegistry.createUnnamedItemForPipe(pipeDefinitionPropolis, item -> { - pipeItemPropolis = item; - item.setRegistryName("pipe_item_propolis"); - item.setUnlocalizedName("buildcraftPipe.pipeitemspropolis"); - item.setCreativeTab(CreativeTabManager.getTab("buildcraft.pipes")); - }); - } - - @SubscribeEvent - public static void registerRecipes(RegistryEvent.Register event) { - Item propolis = ForgeRegistries.ITEMS.getValue(new ResourceLocation("forestry:propolis")); - if (propolis != null && propolis != Items.AIR) { - addPipeRecipe(pipeItemPropolis, propolis, Items.DIAMOND); - } - } - - private static void addPipeRecipe(Item pipe, Object surround) { - addPipeRecipe(pipe, surround, surround); - } - - private static void addPipeRecipe(Item pipe, Object left, Object right) { - // Copied directly from BCTransportRecipes - if (pipe == null) { - return; - } - ItemStack result = new ItemStack(pipe, 8); - IRecipe recipe = new ShapedOreRecipe(pipe.getRegistryName(), result, "lgr", 'l', left, 'r', right, 'g', - "blockGlassColorless"); - recipe.setRegistryName(new ResourceLocation(pipe.getRegistryName() + "_colorless")); - ForgeRegistries.RECIPES.register(recipe); - - for (EnumDyeColor colour : EnumDyeColor.values()) { - ItemStack resultStack = new ItemStack(pipe, 8, colour.getMetadata() + 1); - IRecipe colorRecipe = new ShapedOreRecipe(pipe.getRegistryName(), resultStack, "lgr", 'l', left, 'r', right, - 'g', "blockGlass" + ColourUtil.getName(colour)); - colorRecipe.setRegistryName(new ResourceLocation(pipe.getRegistryName() + "_" + colour)); - ForgeRegistries.RECIPES.register(colorRecipe); - } - } -} diff --git a/common/buildcraft/compat/module/forestry/pipe/PipeBehaviourPropolis.java b/common/buildcraft/compat/module/forestry/pipe/PipeBehaviourPropolis.java deleted file mode 100644 index def558a..0000000 --- a/common/buildcraft/compat/module/forestry/pipe/PipeBehaviourPropolis.java +++ /dev/null @@ -1,196 +0,0 @@ -package buildcraft.compat.module.forestry.pipe; - -import java.io.IOException; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import net.minecraft.client.gui.inventory.GuiContainer; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.inventory.Container; -import net.minecraft.inventory.IInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.network.PacketBuffer; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.world.World; -import net.minecraft.world.WorldServer; - -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - -import buildcraft.api.core.EnumPipePart; -import buildcraft.api.transport.pipe.IPipe; -import buildcraft.api.transport.pipe.PipeBehaviour; -import buildcraft.api.transport.pipe.PipeEventHandler; -import buildcraft.api.transport.pipe.PipeEventItem; - -import buildcraft.lib.cap.CapabilityHelper; - -import buildcraft.compat.CompatUtils; -import buildcraft.compat.network.CompatGui; -import buildcraft.compat.network.IGuiCreator; - -import forestry.api.genetics.AlleleManager; -import forestry.api.genetics.GeneticCapabilities; -import forestry.api.genetics.IFilterLogic; -import forestry.api.genetics.IFilterLogic.INetworkHandler; -import forestry.sorting.DefaultFilterRuleType; -import forestry.sorting.gui.ContainerGeneticFilter; -import forestry.sorting.gui.GuiGeneticFilter; -import forestry.sorting.tiles.IFilterContainer; - -public class PipeBehaviourPropolis extends PipeBehaviour implements IFilterContainer, INetworkHandler, IGuiCreator { - - private final CapabilityHelper caps = new CapabilityHelper(); - private final IFilterLogic filter = AlleleManager.filterRegistry.createLogic(this, this); - - { - caps.addCapabilityInstance(GeneticCapabilities.FILTER_LOGIC, filter, EnumPipePart.VALUES); - caps.addCapabilityInstance(CompatUtils.CAP_GUI_CREATOR, this, EnumPipePart.CENTER); - } - - public PipeBehaviourPropolis(IPipe pipe) { - super(pipe); - } - - public PipeBehaviourPropolis(IPipe pipe, NBTTagCompound nbt) { - super(pipe, nbt); - filter.readFromNBT(nbt.getCompoundTag("filter")); - } - - @Override - public NBTTagCompound writeToNbt() { - NBTTagCompound nbt = super.writeToNbt(); - nbt.setTag("filter", filter.writeToNBT(new NBTTagCompound())); - return nbt; - } - - @Override - public void readPayload(PacketBuffer buffer, Side side, MessageContext ctx) throws IOException { - super.readPayload(buffer, side, ctx); - if (side == Side.CLIENT) { - filter.readGuiData(buffer); - } - } - - @Override - public void writePayload(PacketBuffer buffer, Side side) { - super.writePayload(buffer, side); - if (side == Side.SERVER) { - // FIXME: Inefficient to be sending gui updates all the time - // but fixing this requires proper fixes throughout the net code :/ - filter.writeGuiData(buffer); - } - } - - @Override - public T getCapability(@Nonnull Capability capability, EnumFacing facing) { - T value = caps.getCapability(capability, facing); - if (value != null) { - return value; - } - return super.getCapability(capability, facing); - } - - @Override - public int getTextureIndex(EnumFacing face) { - return face == null ? 0 : face.ordinal() + 1; - } - - @Override - public boolean onPipeActivate(EntityPlayer player, RayTraceResult trace, float hitX, float hitY, float hitZ, - EnumPipePart part) { - if (!getWorldObj().isRemote) { - // TODO: Properly abstract this in to make GUI's a bit more sane! - CompatGui.FORESTRY_PROPOLIS_PIPE.openGui(player, pipe.getHolder().getPipePos()); - // sendUpdatePacket(ImmutableList.of()); - } - return true; - } - - @PipeEventHandler - public void sideCheck(PipeEventItem.SideCheck event) { - ItemStack stack = event.stack; - for (EnumFacing face : EnumFacing.VALUES) { - if (!filter.isValid(stack, face)) { - event.disallow(face); - } else if (filter.getRule(face) == DefaultFilterRuleType.ANYTHING) { - event.decreasePriority(face); - } - } - } - - // IFilterContainer - - @Override - public BlockPos getCoordinates() { - return pipe.getHolder().getPipePos(); - } - - @Override - public World getWorldObj() { - return pipe.getHolder().getPipeWorld(); - } - - @Override - public String getUnlocalizedTitle() { - return ForestryPipes.pipeItemPropolis.getUnlocalizedName() + ".name"; - } - - @Override - @Nullable - public IInventory getBuffer() { - return null; - } - - @Override - public TileEntity getTileEntity() { - return pipe.getHolder().getPipeTile(); - } - - @Override - public IFilterLogic getLogic() { - return filter; - } - - // INetworkHandler - - @Override - public void sendToPlayers(IFilterLogic logic, WorldServer server, EntityPlayer currentPlayer) { - for (EntityPlayer player : server.playerEntities) { - if (player != currentPlayer && player.openContainer instanceof ContainerGeneticFilter) { - ContainerGeneticFilter currentContainer = (ContainerGeneticFilter) currentPlayer.openContainer; - ContainerGeneticFilter otherContainer = (ContainerGeneticFilter) player.openContainer; - if (otherContainer.hasSameTile(currentContainer)) { - otherContainer.setGuiNeedsUpdate(true); - } - } - } - } - - // IGuiCreator - - @Override - public Enum getGuiType() { - return CompatGui.FORESTRY_PROPOLIS_PIPE; - } - - @Override - @Nullable - public Container getServerGuiElement(int data, EntityPlayer player) { - return new ContainerPropolisPipe(this, player); - } - - @Override - @Nullable - @SideOnly(Side.CLIENT) - public GuiContainer getClientGuiElement(int data, EntityPlayer player) { - return new GuiGeneticFilter(this, player.inventory); - } -} diff --git a/common/buildcraft/compat/module/ic2/CompatModuleIndustrialCraft2.java b/common/buildcraft/compat/module/ic2/CompatModuleIndustrialCraft2.java index 01c782d..a44157d 100644 --- a/common/buildcraft/compat/module/ic2/CompatModuleIndustrialCraft2.java +++ b/common/buildcraft/compat/module/ic2/CompatModuleIndustrialCraft2.java @@ -1,37 +1,32 @@ -/* - * Copyright (c) 2020 SpaceToad and the BuildCraft team - * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not - * distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/ - */ - package buildcraft.compat.module.ic2; -import net.minecraft.item.Item; - import buildcraft.compat.CompatModuleBase; - import buildcraft.lib.misc.StackMatchingPredicate; import buildcraft.lib.misc.StackNbtMatcher; import buildcraft.lib.misc.StackUtil; +import net.minecraft.item.Item; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.registries.ForgeRegistries; public class CompatModuleIndustrialCraft2 extends CompatModuleBase { - @Override + public CompatModuleIndustrialCraft2() { + } + public String compatModId() { return "ic2"; } - @Override public void preInit() { - registerCableMatchingPredicate(); + this.registerCableMatchingPredicate(); } private void registerCableMatchingPredicate() { - // Distinguish cables by type and insulation - // https://github.com/BuildCraft/BuildCraft/issues/4553 - Item cable = Item.getByNameOrId("ic2:cable"); +// Item cable = Item.func_111206_d("ic2:cable"); + Item cable = ForgeRegistries.ITEMS.getValue(new ResourceLocation("ic2:cable")); if (cable != null) { - StackMatchingPredicate predicate = new StackNbtMatcher("insulation", "type"); + StackMatchingPredicate predicate = new StackNbtMatcher(new String[] { "insulation", "type" }); StackUtil.registerMatchingPredicate(cable, predicate); } + } } diff --git a/common/buildcraft/compat/module/jei/BCPluginJEI.java b/common/buildcraft/compat/module/jei/BCPluginJEI.java index f31d176..9f286aa 100644 --- a/common/buildcraft/compat/module/jei/BCPluginJEI.java +++ b/common/buildcraft/compat/module/jei/BCPluginJEI.java @@ -1,150 +1,201 @@ package buildcraft.compat.module.jei; -import java.util.Arrays; -import java.util.List; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; - -import net.minecraft.item.ItemStack; - -import net.minecraftforge.fml.common.Loader; - -import buildcraft.api.BCBlocks; import buildcraft.api.BCModules; import buildcraft.api.core.BCLog; import buildcraft.api.enums.EnumEngineType; import buildcraft.api.fuels.IFuel; -import buildcraft.api.recipes.AssemblyRecipeBasic; -import buildcraft.api.recipes.BuildcraftRecipeRegistry; import buildcraft.api.recipes.IRefineryRecipeManager; - -import buildcraft.lib.fluid.FuelRegistry; -import buildcraft.lib.recipe.AssemblyRecipeRegistry; - import buildcraft.compat.module.jei.energy.combustionengine.CategoryCombustionEngine; -import buildcraft.compat.module.jei.energy.combustionengine.HandlerCombustionEngine; import buildcraft.compat.module.jei.factory.CategoryCoolable; import buildcraft.compat.module.jei.factory.CategoryDistiller; import buildcraft.compat.module.jei.factory.CategoryHeatable; -import buildcraft.compat.module.jei.factory.HandlerCoolable; -import buildcraft.compat.module.jei.factory.HandlerDistiller; -import buildcraft.compat.module.jei.factory.HandlerHeatable; -import buildcraft.compat.module.jei.recipe.GuiHandlerBuildCraft; +import buildcraft.compat.module.jei.gui.GuiHandlerBuildCraft; import buildcraft.compat.module.jei.silicon.CategoryAssemblyTable; -import buildcraft.compat.module.jei.silicon.WrapperAssemblyTable; import buildcraft.compat.module.jei.transferhandlers.AdvancedCraftingItemsTransferHandler; import buildcraft.compat.module.jei.transferhandlers.AutoCraftItemsTransferHandler; import buildcraft.core.BCCoreBlocks; +import buildcraft.factory.BCFactoryBlocks; +import buildcraft.lib.gui.GuiBC8; +import buildcraft.lib.recipe.assembly.AssemblyRecipe; +import buildcraft.lib.recipe.assembly.AssemblyRecipeRegistry; +import buildcraft.lib.recipe.fuel.FuelRegistry; +import buildcraft.silicon.BCSiliconBlocks; import buildcraft.silicon.container.ContainerAssemblyTable; - -import mezz.jei.api.IGuiHelper; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; import mezz.jei.api.IModPlugin; -import mezz.jei.api.IModRegistry; -import mezz.jei.api.JEIPlugin; -import mezz.jei.api.recipe.IRecipeCategoryRegistration; -import mezz.jei.api.recipe.VanillaRecipeCategoryUid; +import mezz.jei.api.JeiPlugin; +import mezz.jei.api.constants.VanillaRecipeCategoryUid; +import mezz.jei.api.helpers.IGuiHelper; +import mezz.jei.api.recipe.category.IRecipeCategory; +import mezz.jei.api.registration.*; +import mezz.jei.api.runtime.IJeiRuntime; +import net.minecraft.client.Minecraft; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.ModList; -@JEIPlugin +import java.util.Arrays; +import java.util.List; + +@JeiPlugin public class BCPluginJEI implements IModPlugin { - // public static boolean disableFacadeJEI; - public static IModRegistry registry; + // public static IModRegistry registry; + public static IRecipeRegistration registryRecipe; + public static IGuiHandlerRegistration registryGui; + public static IRecipeTransferRegistration registryRecipeTransfer; + public static IRecipeCatalystRegistration registryRecipeCatalyst; + public static IJeiRuntime jeiRuntime; + + private static final ResourceLocation UID = new ResourceLocation("buildcraft:jei_plugin"); @Override - public void register(IModRegistry registry) { - BCPluginJEI.registry = registry; - registry.addAdvancedGuiHandlers(new GuiHandlerBuildCraft()); -// boolean transport = BCModules.TRANSPORT.isLoaded(); + public ResourceLocation getPluginUid() { + return UID; + } + + + @Override + public void registerGuiHandlers(IGuiHandlerRegistration registry) { + BCPluginJEI.registryGui = registry; + registry.addGenericGuiContainerHandler(GuiBC8.class, new GuiHandlerBuildCraft()); + + } + + // Calen: IRecipeWrapper combined into IRecipeCategory + @Override + public void registerRecipes(IRecipeRegistration registry) { + BCPluginJEI.registryRecipe = registry; boolean factory = BCModules.FACTORY.isLoaded(); boolean energy = BCModules.ENERGY.isLoaded(); boolean silicon = BCModules.SILICON.isLoaded(); -// boolean robotics = BCModules.ROBOTICS.isLoaded(); - if (factory) { - registry.handleRecipes(IRefineryRecipeManager.ICoolableRecipe.class, new HandlerCoolable(), CategoryCoolable.UID); - registry.handleRecipes(IRefineryRecipeManager.IDistillationRecipe.class, new HandlerDistiller(), CategoryDistiller.UID); - registry.handleRecipes(IRefineryRecipeManager.IHeatableRecipe.class, new HandlerHeatable(), CategoryHeatable.UID); - - registry.addRecipes(ImmutableList.copyOf(BuildcraftRecipeRegistry.refineryRecipes.getCoolableRegistry().getAllRecipes()), CategoryCoolable.UID); - registry.addRecipes(ImmutableList.copyOf(BuildcraftRecipeRegistry.refineryRecipes.getDistillationRegistry().getAllRecipes()), CategoryDistiller.UID); - registry.addRecipes(ImmutableList.copyOf(BuildcraftRecipeRegistry.refineryRecipes.getHeatableRegistry().getAllRecipes()), CategoryHeatable.UID); - if (BCBlocks.Factory.DISTILLER != null) { - registry.addRecipeCatalyst(new ItemStack(BCBlocks.Factory.DISTILLER), CategoryDistiller.UID); - } - if (BCBlocks.Factory.HEAT_EXCHANGE != null) { - registry.addRecipeCatalyst(new ItemStack(BCBlocks.Factory.HEAT_EXCHANGE), CategoryCoolable.UID); - registry.addRecipeCatalyst(new ItemStack(BCBlocks.Factory.HEAT_EXCHANGE), CategoryHeatable.UID); - } +// registry.handleRecipes(IRefineryRecipeManager.ICoolableRecipe.class, new HandlerCoolable(), "buildcraft:category_coolable"); +// registry.handleRecipes(IRefineryRecipeManager.IDistillationRecipe.class, new HandlerDistiller(), "buildcraft:category_distiller"); +// registry.handleRecipes(IRefineryRecipeManager.IHeatableRecipe.class, new HandlerHeatable(), "buildcraft:category_heatable"); +// registry.addRecipes(ImmutableList.copyOf(BuildcraftRecipeRegistry.refineryRecipes.getCoolableRegistry().getAllRecipes()), new ResourceLocation("buildcraft:category_coolable")); + registry.addRecipes(ImmutableList.copyOf(Minecraft.getInstance().level.getRecipeManager().getAllRecipesFor(IRefineryRecipeManager.ICoolableRecipe.TYPE)), CategoryCoolable.UID); +// registry.addRecipes(ImmutableList.copyOf(BuildcraftRecipeRegistry.refineryRecipes.getDistillationRegistry().getAllRecipes()), new ResourceLocation("buildcraft:category_distiller")); + registry.addRecipes(ImmutableList.copyOf(Minecraft.getInstance().level.getRecipeManager().getAllRecipesFor(IRefineryRecipeManager.IDistillationRecipe.TYPE)), CategoryDistiller.UID); +// registry.addRecipes(ImmutableList.copyOf(BuildcraftRecipeRegistry.refineryRecipes.getHeatableRegistry().getAllRecipes()), new ResourceLocation("buildcraft:category_heatable")); + registry.addRecipes(ImmutableList.copyOf(Minecraft.getInstance().level.getRecipeManager().getAllRecipesFor(IRefineryRecipeManager.IHeatableRecipe.TYPE)), CategoryHeatable.UID); } + if (energy) { - registry.handleRecipes(IFuel.class, new HandlerCombustionEngine(), CategoryCombustionEngine.UID); - registry.addRecipes(ImmutableList.copyOf(FuelRegistry.INSTANCE.getFuels()), CategoryCombustionEngine.UID); - if (BCCoreBlocks.engine != null){ - if (BCCoreBlocks.engine.isRegistered(EnumEngineType.STONE)) { - registry.addRecipeCatalyst(BCCoreBlocks.engine.getStack(EnumEngineType.STONE), VanillaRecipeCategoryUid.FUEL); - } - if (BCCoreBlocks.engine.isRegistered(EnumEngineType.IRON)) { - registry.addRecipeCatalyst(BCCoreBlocks.engine.getStack(EnumEngineType.IRON), CategoryCombustionEngine.UID); - } - } +// registry.handleRecipes(IFuel.class, new HandlerCombustionEngine(), "buildcraft-compat:engine.combustion"); +// registry.addRecipes(ImmutableList.copyOf(FuelRegistry.INSTANCE.getFuels()), new ResourceLocation("buildcraft-compat:engine.combustion")); + registry.addRecipes(ImmutableList.copyOf(Minecraft.getInstance().level.getRecipeManager().getAllRecipesFor(IFuel.TYPE)), CategoryCombustionEngine.UID); } - if (silicon) { - registry.handleRecipes(AssemblyRecipeBasic.class, WrapperAssemblyTable::new, CategoryAssemblyTable.UID); -// registry.handleRecipes(IntegrationRecipe.class, new HandlerIntegrationTable(), CategoryIntegrationTable.UID); - registry.addRecipes(ImmutableList.copyOf(AssemblyRecipeRegistry.REGISTRY.values()), CategoryAssemblyTable.UID); -// registry.addRecipes(ImmutableList.copyOf(IntegrationRecipeRegistry.INSTANCE.getAllRecipes()), CategoryIntegrationTable.UID); - if (BCBlocks.Silicon.ASSEMBLY_TABLE != null) { - registry.addRecipeCatalyst(new ItemStack(BCBlocks.Silicon.ASSEMBLY_TABLE), CategoryAssemblyTable.UID); - } - if (BCBlocks.Silicon.ADVANCED_CRAFTING_TABLE != null) { - registry.addRecipeCatalyst(new ItemStack(BCBlocks.Silicon.ADVANCED_CRAFTING_TABLE), VanillaRecipeCategoryUid.CRAFTING); - } + if (silicon) { +// registry.handleRecipes(AssemblyRecipeBasic.class, WrapperAssemblyTable::new, "buildcraft-compat:silicon.assembly"); +// registry.addRecipes(ImmutableList.copyOf(AssemblyRecipeRegistry.REGISTRY.values()), new ResourceLocation("buildcraft-compat:silicon.assembly")); + registry.addRecipes(ImmutableList.copyOf(Minecraft.getInstance().level.getRecipeManager().getAllRecipesFor(AssemblyRecipe.TYPE)), CategoryAssemblyTable.UID); } + } - registry.getRecipeTransferRegistry().addRecipeTransferHandler(new AutoCraftItemsTransferHandler(), VanillaRecipeCategoryUid.CRAFTING); - registry.getRecipeTransferRegistry().addRecipeTransferHandler(new AdvancedCraftingItemsTransferHandler(), VanillaRecipeCategoryUid.CRAFTING); - // registry.getRecipeTransferRegistry().addRecipeTransferHandler(new AssemblyTableTransferHandler(), CategoryAssemblyTable.UID); - registry.getRecipeTransferRegistry().addRecipeTransferHandler(ContainerAssemblyTable.class, CategoryAssemblyTable.UID, - 36, 12, 0, 36); + @Override + public void registerRecipeTransferHandlers(IRecipeTransferRegistration registry) { + BCPluginJEI.registryRecipeTransfer = registry; + +// registry.addRecipeTransferHandler(new AutoCraftItemsTransferHandler(), "minecraft.crafting"); + registry.addRecipeTransferHandler(new AutoCraftItemsTransferHandler(), VanillaRecipeCategoryUid.CRAFTING); +// registry.addRecipeTransferHandler(new AdvancedCraftingItemsTransferHandler(), "minecraft.crafting"); + registry.addRecipeTransferHandler(new AdvancedCraftingItemsTransferHandler(), VanillaRecipeCategoryUid.CRAFTING); +// registry.addRecipeTransferHandler(ContainerAssemblyTable.class, "buildcraft-compat:silicon.assembly", 36, 12, 0, 36); + registry.addRecipeTransferHandler(ContainerAssemblyTable.class, CategoryAssemblyTable.UID, 36, 12, 0, 36); } @Override public void registerCategories(IRecipeCategoryRegistration registry) { -// boolean transport = Loader.isModLoaded(BCModules.TRANSPORT.getModId()); - boolean factory = Loader.isModLoaded(BCModules.FACTORY.getModId()); - boolean energy = Loader.isModLoaded(BCModules.ENERGY.getModId()); - boolean silicon = Loader.isModLoaded(BCModules.SILICON.getModId()); -// boolean robotics = Loader.isModLoaded(BCModules.ROBOTICS.getModId()); - +// boolean factory = Loader.isModLoaded(BCModules.FACTORY.getModId()); + boolean factory = ModList.get().isLoaded(BCModules.FACTORY.getModId()); +// boolean energy = Loader.isModLoaded(BCModules.ENERGY.getModId()); + boolean energy = ModList.get().isLoaded(BCModules.ENERGY.getModId()); +// boolean silicon = Loader.isModLoaded(BCModules.SILICON.getModId()); + boolean silicon = ModList.get().isLoaded(BCModules.SILICON.getModId()); List lst = Lists.newArrayList(); IGuiHelper helper = registry.getJeiHelpers().getGuiHelper(); - -// jeiRegistry.addAdvancedGuiHandlers(new LedgerGuiHandler()); -// if (transport) { -// lst.add("transport"); -// loadTransport(jeiRegistry); -// } if (factory) { lst.add("factory"); - registry.addRecipeCategories(new CategoryHeatable(helper)); - registry.addRecipeCategories(new CategoryDistiller(helper)); - registry.addRecipeCategories(new CategoryCoolable(helper)); + registry.addRecipeCategories(new IRecipeCategory[] { new CategoryHeatable(helper) }); + registry.addRecipeCategories(new IRecipeCategory[] { new CategoryDistiller(helper) }); + registry.addRecipeCategories(new IRecipeCategory[] { new CategoryCoolable(helper) }); } + if (energy) { lst.add("energy"); - registry.addRecipeCategories(new CategoryCombustionEngine(helper)); +// registry.addRecipeCategories(new IRecipeCategory[]{new CategoryCombustionEngine(helper)}); + registry.addRecipeCategories(new IRecipeCategory[] { new CategoryCombustionEngine(helper, FuelRegistry.INSTANCE.getFuels(Minecraft.getInstance().level)) }); } + if (silicon) { lst.add("silicon"); - registry.addRecipeCategories(new CategoryAssemblyTable(helper)); -// registry.addRecipeCategories(new CategoryIntegrationTable(helper)); +// registry.addRecipeCategories(new IRecipeCategory[]{new CategoryAssemblyTable(helper)}); + registry.addRecipeCategories(new IRecipeCategory[] { new CategoryAssemblyTable(helper, AssemblyRecipeRegistry.getAll(Minecraft.getInstance().level)) }); } BCLog.logger.info("Loaded JEI mods: " + Arrays.toString(lst.toArray())); } -// private static void loadTransport(IModRegistry jeiRegistry) { -// jeiRegistry.addAdvancedGuiHandlers(new GateGuiHandler()); -// } + @Override + public void registerRecipeCatalysts(IRecipeCatalystRegistration registry) { + BCPluginJEI.registryRecipeCatalyst = registry; + + boolean factory = BCModules.FACTORY.isLoaded(); + boolean energy = BCModules.ENERGY.isLoaded(); + boolean silicon = BCModules.SILICON.isLoaded(); + if (factory) { + if (BCFactoryBlocks.distiller != null) { +// registry.addRecipeCatalyst(new ItemStack(BCFactoryBlocks.distiller.get()), new String[]{"buildcraft:category_distiller"}); + registry.addRecipeCatalyst(new ItemStack(BCFactoryBlocks.distiller.get()), CategoryDistiller.UID); + } + + if (BCFactoryBlocks.heatExchange != null) { +// registry.addRecipeCatalyst(new ItemStack(BCFactoryBlocks.heatExchange.get()), new String[]{"buildcraft:category_coolable"}); + registry.addRecipeCatalyst(new ItemStack(BCFactoryBlocks.heatExchange.get()), CategoryCoolable.UID); +// registry.addRecipeCatalyst(new ItemStack(BCFactoryBlocks.heatExchange.get()), new String[]{"buildcraft:category_heatable"}); + registry.addRecipeCatalyst(new ItemStack(BCFactoryBlocks.heatExchange.get()), CategoryHeatable.UID); + } + + if (BCFactoryBlocks.autoWorkbenchItems != null) { + registry.addRecipeCatalyst(new ItemStack(BCFactoryBlocks.autoWorkbenchItems.get()), VanillaRecipeCategoryUid.CRAFTING); + } + } + + if (energy) { +// if (BCCoreBlocks.engine != null) + if (!BCCoreBlocks.engineBlockMap.isEmpty()) { +// if (BCCoreBlocks.engine.isRegistered(EnumEngineType.STONE)) + if (BCCoreBlocks.engineBlockMap.containsKey(EnumEngineType.STONE)) { +// registry.addRecipeCatalyst(BCCoreBlocks.engine.getStack(EnumEngineType.STONE), new String[]{"minecraft.fuel"}); + registry.addRecipeCatalyst(new ItemStack(BCCoreBlocks.engineBlockMap.get(EnumEngineType.STONE).get()), VanillaRecipeCategoryUid.FUEL); + } + +// if (BCCoreBlocks.engine.isRegistered(EnumEngineType.IRON)) + if (BCCoreBlocks.engineBlockMap.containsKey(EnumEngineType.IRON)) { +//// registry.addRecipeCatalyst(BCCoreBlocks.engine.getStack(EnumEngineType.IRON), new String[]{"buildcraft-compat:engine.combustion"}); +// registry.addRecipeCatalyst(new ItemStack(BCCoreBlocks.engineBlockMap.get(EnumEngineType.IRON).get()), new String[]{"buildcraft-compat:engine.combustion"}); + registry.addRecipeCatalyst(new ItemStack(BCCoreBlocks.engineBlockMap.get(EnumEngineType.IRON).get()), CategoryCombustionEngine.UID); + } + } + } + + if (silicon) { + if (BCSiliconBlocks.assemblyTable != null) { +// registry.addRecipeCatalyst(new ItemStack(BCSiliconBlocks.assemblyTable.get()), new String[]{"buildcraft-compat:silicon.assembly"}); + registry.addRecipeCatalyst(new ItemStack(BCSiliconBlocks.assemblyTable.get()), CategoryAssemblyTable.UID); + } + + if (BCSiliconBlocks.advancedCraftingTable != null) { +// registry.addRecipeCatalyst(new ItemStack(BCSiliconBlocks.advancedCraftingTable.get()), new String[]{"minecraft.crafting"}); + registry.addRecipeCatalyst(new ItemStack(BCSiliconBlocks.advancedCraftingTable.get()), VanillaRecipeCategoryUid.CRAFTING); + } + } + } + + @Override + public void onRuntimeAvailable(IJeiRuntime jeiRuntime) { + BCPluginJEI.jeiRuntime = jeiRuntime; + } } diff --git a/common/buildcraft/compat/module/jei/energy/combustionengine/CategoryCombustionEngine.java b/common/buildcraft/compat/module/jei/energy/combustionengine/CategoryCombustionEngine.java index 323ec89..9170081 100644 --- a/common/buildcraft/compat/module/jei/energy/combustionengine/CategoryCombustionEngine.java +++ b/common/buildcraft/compat/module/jei/energy/combustionengine/CategoryCombustionEngine.java @@ -1,40 +1,87 @@ package buildcraft.compat.module.jei.energy.combustionengine; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.fluids.FluidStack; import buildcraft.api.BCModules; -import mezz.jei.api.IGuiHelper; -import mezz.jei.api.gui.IDrawable; -import mezz.jei.api.gui.IGuiFluidStackGroup; +import buildcraft.api.fuels.IFuel; +import buildcraft.api.fuels.IFuelManager; +import buildcraft.api.fuels.IFuelManager.IDirtyFuel; +import buildcraft.api.mj.MjAPI; +import buildcraft.energy.BCEnergyBlocks; +import com.google.common.collect.Lists; +import com.mojang.blaze3d.matrix.MatrixStack; +import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.gui.IRecipeLayout; +import mezz.jei.api.gui.drawable.IDrawable; +import mezz.jei.api.gui.drawable.IDrawableAnimated; +import mezz.jei.api.gui.drawable.IDrawableStatic; +import mezz.jei.api.gui.ingredient.IGuiFluidStackGroup; +import mezz.jei.api.helpers.IGuiHelper; import mezz.jei.api.ingredients.IIngredients; -import mezz.jei.api.recipe.BlankRecipeCategory; +import mezz.jei.api.recipe.category.IRecipeCategory; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TranslationTextComponent; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fluids.FluidStack; -public class CategoryCombustionEngine extends BlankRecipeCategory { - public static final String UID = "buildcraft-compat:engine.combustion"; +import java.awt.*; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +//public class CategoryCombustionEngine extends BlankRecipeCategory +public class CategoryCombustionEngine implements IRecipeCategory { + // public static final ResourceLocation UID = new ResourceLocation("buildcraft-compat:engine.combustion"); + public static final ResourceLocation UID = new ResourceLocation(BCModules.ENERGY.getModId(), "engine_combustion"); + public static final ResourceLocation FURNACE = new ResourceLocation("minecraft", "textures/gui/container/furnace.png"); private final IDrawable background; -// private WrapperCombustionEngine wrapper = null; - public CategoryCombustionEngine(IGuiHelper guiHelper) { - super(); - this.background = guiHelper.createDrawable( - new ResourceLocation("minecraft", "textures/gui/container/furnace.png"), - 55, 38, 18, 32, 0, 0, 0, 80); + private final IDrawable icon; + + @OnlyIn(Dist.CLIENT) + private FontRenderer font = Minecraft.getInstance().font; + private final Map burnTimeDrabableMap = new HashMap<>(); + + public CategoryCombustionEngine(IGuiHelper guiHelper, Collection fuels) { + // Calen: 80->100 +// this.background = guiHelper.createDrawable(new ResourceLocation("minecraft", "textures/gui/container/furnace.png"), 55, 38, 18, 32, 0, 0, 0, 80); +// this.background = guiHelper.drawableBuilder(FURNACE, 55, 38, 18, 32).addPadding(0, 0, 0, 80).build(); + this.background = guiHelper.drawableBuilder(FURNACE, 55, 38, 18, 32).addPadding(0, 0, 0, 120).build(); + // Calen: from 1.12.2 what is this doing??? guiHelper.createDrawable(new ResourceLocation(BCModules.ENERGY.getModId(), ""), 0, 0, 16, 16); + + this.icon = guiHelper.createDrawableIngredient(new ItemStack(BCEnergyBlocks.engineIron.get())); + +// ResourceLocation furnaceBackgroundLocation = new ResourceLocation("minecraft", "textures/gui/container/furnace.png"); + IDrawableStatic flameDrawable = guiHelper.createDrawable(FURNACE, 176, 0, 14, 14); +// this.flame = guiHelper.createAnimatedDrawable(flameDrawable, fuel.getTotalBurningTime() / 10, IDrawableAnimated.StartDirection.TOP, true); + for (IFuel fuel : fuels) { + if (!burnTimeDrabableMap.containsKey(fuel.getTotalBurningTime())) { + burnTimeDrabableMap.put(fuel.getTotalBurningTime(), guiHelper.createAnimatedDrawable(flameDrawable, fuel.getTotalBurningTime() / 10, IDrawableAnimated.StartDirection.TOP, true)); + } + } } @Override - public String getUid() { + public ResourceLocation getUid() { return UID; } @Override - public String getTitle() { - return "Combustion Engine Fuels"; + public Class getRecipeClass() { + return IFuel.class; } @Override + public String getTitle() { +// return new TextComponent("Combustion Engine Fuels"); + return new TranslationTextComponent("buildcraft.jei.title.combustion_engine_fuels").getString(); + } + public String getModName() { return BCModules.ENERGY.name(); } @@ -45,27 +92,68 @@ public IDrawable getBackground() { } @Override - public void setRecipe(IRecipeLayout recipeLayout, WrapperCombustionEngine recipeWrapper, IIngredients ingredients) { -// WrapperCombustionEngine wrapper = (WrapperCombustionEngine) recipeWrapper; - IGuiFluidStackGroup guiFluidStacks = recipeLayout.getFluidStacks(); + public IDrawable getIcon() { + return this.icon; + } - guiFluidStacks.init(0, true, 1, 15, 16, 16, 1000, false, null); - guiFluidStacks.set(0, ingredients.getInputs(FluidStack.class).get(0)); + @Override + public void setIngredients(IFuel recipe, IIngredients ingredients) { + ingredients.setInput(VanillaTypes.FLUID, recipe.getFluid()); + if (recipe instanceof IDirtyFuel) { + ingredients.setOutput(VanillaTypes.FLUID, ((IDirtyFuel) recipe).getResidue()); + } + } + + // Calen + private int lastBurnTime = -1; - if (recipeWrapper instanceof WrapperCombustionEngine.Dirty) { -// WrapperCombustionEngine.Dirty dirty = (WrapperCombustionEngine.Dirty)recipeWrapper; + @Override + public void draw(IFuel fuel, MatrixStack stack, double mouseX, double mouseY) { +// this.flame.draw(stack, 2, 0); + this.burnTimeDrabableMap.get(fuel.getTotalBurningTime()).draw(stack, 2, 0); +// GlStateManager.func_179094_E(); + stack.pushPose(); + // Calen: 8->6 +// GlStateManager.func_179109_b(24.0F, 8.0F, 0.0F); +// stack.translate(24.0F, 8.0F, 0.0F); + stack.translate(24.0F, 6.0F, 0.0F); +// this.font.draw(stack, "Burns for " + fuel.getTotalBurningTime() / 20 + "s", 0, 0, Color.darkGray.getRGB()); + this.font.draw(stack, new TranslationTextComponent("buildcraft.jei.title.combustion_engine_fuels.burn_time", fuel.getTotalBurningTime() / 20).getString(), 0, 0, Color.darkGray.getRGB()); +// this.font.draw(stack, " at " + MjAPI.formatMj(fuel.getPowerPerCycle()) + " MJ/t", 0, font.lineHeight, Color.darkGray.getRGB()); + this.font.draw(stack, new TranslationTextComponent("buildcraft.jei.title.combustion_engine_fuels.burn_speed", MjAPI.formatMj(fuel.getPowerPerCycle())).getString(), 0, font.lineHeight, Color.darkGray.getRGB()); +// GlStateManager.func_179109_b(0.0F, (float)(minecraft.field_71466_p.field_78288_b * 2), 0.0F); + stack.translate(0.0F, (float) (font.lineHeight * 2), 0.0F); +// GlStateManager.func_179139_a(0.7, 0.7, 1.0); + stack.scale(0.7F, 0.7F, 1.0F); +// this.font.draw(stack, " total " + MjAPI.formatMj(fuel.getPowerPerCycle() * (long) fuel.getTotalBurningTime()) + " MJ", 1, 2, Color.gray.getRGB()); + this.font.draw(stack, new TranslationTextComponent("buildcraft.jei.title.combustion_engine_fuels.burn_total", MjAPI.formatMj(fuel.getPowerPerCycle() * (long) fuel.getTotalBurningTime())).getString(), 1, 2, Color.gray.getRGB()); +// GlStateManager.func_179121_F(); + stack.popPose(); + } - guiFluidStacks.init(1, false, 95, 15, 16, 16, 1000, false, null); - guiFluidStacks.set(1, ingredients.getOutputs(FluidStack.class).get(0)); + @Override + // public void setRecipe(IRecipeLayout recipeLayout, WrapperCombustionEngine recipeWrapper, IIngredients ingredients) + public void setRecipe(IRecipeLayout recipeLayout, IFuel fuel, IIngredients ingredients) { + IGuiFluidStackGroup guiFluidStacks = recipeLayout.getFluidStacks(); + guiFluidStacks.init(0, true, 1, 15, 16, 16, 1000, false, null); + guiFluidStacks.set(0, new FluidStack(fuel.getFluid(), 1000)); + if (fuel instanceof IFuelManager.IDirtyFuel) { + IFuelManager.IDirtyFuel dirtyFuel = (IFuelManager.IDirtyFuel) fuel; + // Calen: move right 20 to not covered the text +// guiFluidStacks.init(1, false, 95, 15, 16, 16, 1000, false, (IDrawable) null); + guiFluidStacks.init(1, false, 115, 15, 16, 16, 1000, false, (IDrawable) null); +// guiFluidStacks.set(1, (List) ingredients.getOutputs(FluidStack.class).get(0)); + guiFluidStacks.set(1, dirtyFuel.getResidue()); } } -// -// @Override -// public void drawExtras(Minecraft minecraft) { -// super.drawExtras(minecraft); -// -// if (this.wrapper != null) { -// this.wrapper.flame.draw(minecraft, 2, 0); -// } -// } + + @Override + public List getTooltipStrings(IFuel recipe, double mouseX, double mouseY) { + return Lists.newArrayList(); + } + + @Override + public boolean handleClick(IFuel recipe, double mouseX, double mouseY, int mouseButton) { + return false; + } } diff --git a/common/buildcraft/compat/module/jei/energy/combustionengine/HandlerCombustionEngine.java b/common/buildcraft/compat/module/jei/energy/combustionengine/HandlerCombustionEngine.java deleted file mode 100644 index 7a4a0f0..0000000 --- a/common/buildcraft/compat/module/jei/energy/combustionengine/HandlerCombustionEngine.java +++ /dev/null @@ -1,19 +0,0 @@ -package buildcraft.compat.module.jei.energy.combustionengine; - -import buildcraft.api.fuels.IFuel; -import buildcraft.api.fuels.IFuelManager.IDirtyFuel; - -import buildcraft.compat.module.jei.BCPluginJEI; - -import mezz.jei.api.recipe.IRecipeWrapper; -import mezz.jei.api.recipe.IRecipeWrapperFactory; - -public class HandlerCombustionEngine implements IRecipeWrapperFactory { - @Override - public IRecipeWrapper getRecipeWrapper(IFuel recipe) { - if (recipe instanceof IDirtyFuel) { - return new WrapperCombustionEngine.Dirty(BCPluginJEI.registry.getJeiHelpers().getGuiHelper(), (IDirtyFuel) recipe); - } - return new WrapperCombustionEngine(BCPluginJEI.registry.getJeiHelpers().getGuiHelper(), recipe); - } -} diff --git a/common/buildcraft/compat/module/jei/energy/combustionengine/WrapperCombustionEngine.java b/common/buildcraft/compat/module/jei/energy/combustionengine/WrapperCombustionEngine.java deleted file mode 100644 index d50d9f0..0000000 --- a/common/buildcraft/compat/module/jei/energy/combustionengine/WrapperCombustionEngine.java +++ /dev/null @@ -1,110 +0,0 @@ -package buildcraft.compat.module.jei.energy.combustionengine; - -import java.awt.Color; -import java.util.List; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.fluids.Fluid; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; -import buildcraft.api.fuels.IFuel; -import buildcraft.api.fuels.IFuelManager.IDirtyFuel; -import buildcraft.api.mj.MjAPI; -import mezz.jei.api.IGuiHelper; -import mezz.jei.api.gui.IDrawableAnimated; -import mezz.jei.api.gui.IDrawableStatic; -import mezz.jei.api.ingredients.IIngredients; -import mezz.jei.api.recipe.IRecipeWrapper; - -public class WrapperCombustionEngine implements IRecipeWrapper { - private final IFuel fuel; - private final ImmutableList in; - private final IDrawableAnimated flame; - - WrapperCombustionEngine(IGuiHelper guiHelper, IFuel fuel) { - this.fuel = fuel; - in = ImmutableList.of(new FluidStack(fuel.getFluid(), Fluid.BUCKET_VOLUME)); - - ResourceLocation furnaceBackgroundLocation = new ResourceLocation("minecraft", "textures/gui/container/furnace.png"); - IDrawableStatic flameDrawable = guiHelper.createDrawable(furnaceBackgroundLocation, 176, 0, 14, 14); - this.flame = guiHelper.createAnimatedDrawable(flameDrawable, fuel.getTotalBurningTime() / 10, IDrawableAnimated.StartDirection.TOP, true); - } - -// @Override -// public List getInputs() { -// return Collections.emptyList(); -// } -// -// @Override -// public List getOutputs() { -// return Collections.emptyList(); -// } -// -// @Override -// public List getFluidInputs() { -// return in; -// } -// -// @Override -// public List getFluidOutputs() { -// return null; -// } -// -// @Override -// public void drawInfo(Minecraft minecraft, int recipeWidth, int recipeHeight) {} - - @Override - public void getIngredients(IIngredients ingredients) { - ingredients.setInputs(FluidStack.class, this.in); - } - - @Override - @SideOnly(Side.CLIENT) - public void drawInfo(Minecraft minecraft, int recipeWidth, int recipeHeight, int mouseX, int mouseY) { - this.flame.draw(minecraft, 2, 0); - - GlStateManager.pushMatrix(); - GlStateManager.translate(24, 8, 0); - // GlStateManager.scale(.7, .7, 1.0); - minecraft.fontRenderer.drawString("Burns for " + (fuel.getTotalBurningTime() / 20) + "s", 0, 0, Color.darkGray.getRGB()); - minecraft.fontRenderer.drawString(" at " + MjAPI.formatMj(fuel.getPowerPerCycle()) + " MJ/t", 0, minecraft.fontRenderer.FONT_HEIGHT, Color.darkGray.getRGB()); - GlStateManager.translate(0, minecraft.fontRenderer.FONT_HEIGHT * 2, 0); - GlStateManager.scale(.7, .7, 1.0); - minecraft.fontRenderer.drawString(" total " + MjAPI.formatMj(fuel.getPowerPerCycle() * fuel.getTotalBurningTime()) + " MJ", 1, 2, Color.gray.getRGB()); - GlStateManager.popMatrix(); - } - -// @Override -// public void drawAnimations(Minecraft minecraft, int recipeWidth, int recipeHeight) { -// flame.draw(minecraft, 2, 0); -// } - - @Override - public List getTooltipStrings(int mouseX, int mouseY) { - return Lists.newArrayList(); - } - - @Override - public boolean handleClick(Minecraft minecraft, int mouseX, int mouseY, int mouseButton) { - return false; - } - - public static class Dirty extends WrapperCombustionEngine { - final IDirtyFuel dirty; - - Dirty(IGuiHelper guiHelper, IDirtyFuel fuel) { - super(guiHelper, fuel); - this.dirty = fuel; - } - - @Override - public void getIngredients(IIngredients ingredients) { - super.getIngredients(ingredients); - ingredients.setOutput(FluidStack.class, this.dirty.getResidue()); - } - } -} diff --git a/common/buildcraft/compat/module/jei/energy/combustionengine/package-info.java b/common/buildcraft/compat/module/jei/energy/combustionengine/package-info.java index 1cad84d..19274a6 100644 --- a/common/buildcraft/compat/module/jei/energy/combustionengine/package-info.java +++ b/common/buildcraft/compat/module/jei/energy/combustionengine/package-info.java @@ -2,5 +2,6 @@ @MethodsReturnNonnullByDefault package buildcraft.compat.module.jei.energy.combustionengine; +import mezz.jei.api.MethodsReturnNonnullByDefault; + import javax.annotation.ParametersAreNonnullByDefault; -import mcp.MethodsReturnNonnullByDefault; diff --git a/common/buildcraft/compat/module/jei/factory/CategoryCoolable.java b/common/buildcraft/compat/module/jei/factory/CategoryCoolable.java index 426d952..cc7ecbf 100644 --- a/common/buildcraft/compat/module/jei/factory/CategoryCoolable.java +++ b/common/buildcraft/compat/module/jei/factory/CategoryCoolable.java @@ -1,64 +1,125 @@ package buildcraft.compat.module.jei.factory; -import net.minecraft.client.Minecraft; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.fluids.FluidStack; import buildcraft.api.BCModules; -import mezz.jei.api.IGuiHelper; -import mezz.jei.api.gui.IDrawable; -import mezz.jei.api.gui.IGuiFluidStackGroup; +import buildcraft.api.recipes.IRefineryRecipeManager; +import buildcraft.api.recipes.IRefineryRecipeManager.ICoolableRecipe; +import buildcraft.factory.BCFactoryBlocks; +import buildcraft.lib.misc.StackUtil; +import com.google.common.collect.Lists; +import com.mojang.blaze3d.matrix.MatrixStack; +import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.gui.IRecipeLayout; +import mezz.jei.api.gui.drawable.IDrawable; +import mezz.jei.api.gui.drawable.IDrawableAnimated; +import mezz.jei.api.gui.drawable.IDrawableStatic; +import mezz.jei.api.gui.ingredient.IGuiFluidStackGroup; +import mezz.jei.api.helpers.IGuiHelper; import mezz.jei.api.ingredients.IIngredients; -import mezz.jei.api.recipe.BlankRecipeCategory; +import mezz.jei.api.recipe.category.IRecipeCategory; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TranslationTextComponent; + +import java.util.List; -public class CategoryCoolable extends BlankRecipeCategory { - public static final String UID = "buildcraft:category_coolable"; +//public class CategoryCoolable extends BlankRecipeCategory +public class CategoryCoolable implements IRecipeCategory { + public static final ResourceLocation UID = new ResourceLocation(BCModules.FACTORY.getModId(), "category_coolable"); public static final ResourceLocation heatExchangerBackground = new ResourceLocation("buildcraftfactory:textures/gui/heat_exchanger.png"); + private final IDrawable background; + private final IDrawable slot; + + private final IDrawable icon; + + private final IDrawableAnimated animatedCooling; + private final IDrawableAnimated animatedHeating; + + public CategoryCoolable(IGuiHelper guiHelper) { + // Calen: top padding add 2 to be same height as heatable +// this.background = helper.createDrawable(heatExchangerBackground, 61, 38, 54, 17, 0, 0, 18, 80); +// this.background = guiHelper.drawableBuilder(heatExchangerBackground, 61, 38, 54, 17).addPadding(0, 0, 18, 80).build(); + this.background = guiHelper.drawableBuilder(heatExchangerBackground, 61, 38, 54, 17).addPadding(2, 0, 18, 80).build(); + this.slot = guiHelper.createDrawable(heatExchangerBackground, 7, 22, 18, 18); - private final IDrawable background, slot; + this.icon = guiHelper.createDrawableIngredient(new ItemStack(BCFactoryBlocks.heatExchange.get())); - public CategoryCoolable(IGuiHelper helper) { - this.background = helper.createDrawable(heatExchangerBackground, 61, 38, 54, 17, 0, 0, 18, 80); - this.slot = helper.createDrawable(heatExchangerBackground, 7, 22, 18, 18); + IDrawableStatic overComplete = guiHelper.createDrawable(CategoryCoolable.heatExchangerBackground, 52, 171, 54, 17); + this.animatedCooling = guiHelper.createAnimatedDrawable(overComplete, 40, IDrawableAnimated.StartDirection.LEFT, false); + overComplete = guiHelper.createDrawable(CategoryCoolable.heatExchangerBackground, 52, 188, 54, 17); + this.animatedHeating = guiHelper.createAnimatedDrawable(overComplete, 40, IDrawableAnimated.StartDirection.RIGHT, false); } - @Override - public String getUid() { + public ResourceLocation getUid() { return UID; } @Override + public Class getRecipeClass() { + return IRefineryRecipeManager.ICoolableRecipe.class; + } + public String getTitle() { - return "Coolable Fluids"; +// return new TextComponent("Coolable Fluids"); + return new TranslationTextComponent("buildcraft.jei.title.coolable_fluids").getString(); } - @Override public String getModName() { return BCModules.FACTORY.name(); } - @Override public IDrawable getBackground() { return this.background; } @Override - public void drawExtras(Minecraft minecraft) { - slot.draw(minecraft, 0, 0); - slot.draw(minecraft, 72, 0); + public IDrawable getIcon() { + return this.icon; } -// -// @Override -// public void drawAnimations(Minecraft minecraft) {} @Override - public void setRecipe(IRecipeLayout recipeLayout, WrapperCoolable recipeWrapper, IIngredients ingredients) { + public void setIngredients(ICoolableRecipe recipe, IIngredients ingredients) { + ingredients.setInput(VanillaTypes.FLUID, recipe.in()); + ingredients.setOutput(VanillaTypes.FLUID, recipe.out() == null ? StackUtil.EMPTY_FLUID : recipe.out()); + } + + @Override +// public void drawExtras(Minecraft minecraft) + public void draw(IRefineryRecipeManager.ICoolableRecipe recipe, MatrixStack stack, double mouseX, double mouseY) { + // Calen: y+1 to be at the same height as tubes of background + // in 1.18.2 additionally +1 +// this.slot.draw(stack, 0, 0); + this.slot.draw(stack, 0, 1); +// this.slot.draw(stack, 72, 0); + this.slot.draw(stack, 72, 1); + + // Calen: top padding add 2 to be same height as heatable +// this.animatedCooling.draw(stack, 18, 0); + this.animatedCooling.draw(stack, 18, 2); +// this.animatedHeating.draw(stack, 18, 0); + this.animatedHeating.draw(stack, 18, 2); + } + + @Override +// public void setRecipe(IRecipeLayout recipeLayout, WrapperCoolable recipeWrapper, IIngredients ingredients) + public void setRecipe(IRecipeLayout recipeLayout, ICoolableRecipe recipe, IIngredients ingredients) { IGuiFluidStackGroup guiFluidStacks = recipeLayout.getFluidStacks(); +// guiFluidStacks.init(0, true, 1, 1, 16, 16, 10, false, (IDrawable) null); + guiFluidStacks.init(0, true, 1, 2, 16, 16, 10, false, (IDrawable) null); + guiFluidStacks.set(0, recipe.in()); +// guiFluidStacks.init(1, false, 73, 1, 16, 16, 10, false, (IDrawable) null); + guiFluidStacks.init(1, false, 73, 2, 16, 16, 10, false, (IDrawable) null); +// guiFluidStacks.set(1, (List) ingredients.getOutputs(FluidStack.class).get(0)); + guiFluidStacks.set(1, recipe.out() == null ? StackUtil.EMPTY_FLUID : recipe.out()); + } - guiFluidStacks.init(0, true, 1, 1, 16, 16, 10, false, null); - guiFluidStacks.set(0, ingredients.getInputs(FluidStack.class).get(0)); + @Override + public List getTooltipStrings(ICoolableRecipe recipe, double mouseX, double mouseY) { + return Lists.newArrayList(); + } - guiFluidStacks.init(1, false, 73, 1, 16, 16, 10, false, null); - guiFluidStacks.set(1, ingredients.getOutputs(FluidStack.class).get(0)); + @Override + public boolean handleClick(IRefineryRecipeManager.ICoolableRecipe recipe, double mouseX, double mouseY, int mouseButton) { + return false; } } diff --git a/common/buildcraft/compat/module/jei/factory/CategoryDistiller.java b/common/buildcraft/compat/module/jei/factory/CategoryDistiller.java index 64f4501..c70c16b 100644 --- a/common/buildcraft/compat/module/jei/factory/CategoryDistiller.java +++ b/common/buildcraft/compat/module/jei/factory/CategoryDistiller.java @@ -1,70 +1,130 @@ package buildcraft.compat.module.jei.factory; -import net.minecraft.client.Minecraft; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.fluids.FluidStack; import buildcraft.api.BCModules; -import mezz.jei.api.IGuiHelper; -import mezz.jei.api.gui.IDrawable; -import mezz.jei.api.gui.IGuiFluidStackGroup; +import buildcraft.api.mj.MjAPI; +import buildcraft.api.recipes.IRefineryRecipeManager; +import buildcraft.api.recipes.IRefineryRecipeManager.IDistillationRecipe; +import buildcraft.factory.BCFactoryBlocks; +import com.google.common.collect.Lists; +import com.mojang.blaze3d.matrix.MatrixStack; +import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.gui.IRecipeLayout; +import mezz.jei.api.gui.drawable.IDrawable; +import mezz.jei.api.gui.drawable.IDrawableAnimated; +import mezz.jei.api.gui.drawable.IDrawableStatic; +import mezz.jei.api.gui.ingredient.IGuiFluidStackGroup; +import mezz.jei.api.helpers.IGuiHelper; import mezz.jei.api.ingredients.IIngredients; -import mezz.jei.api.recipe.BlankRecipeCategory; +import mezz.jei.api.recipe.category.IRecipeCategory; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TranslationTextComponent; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +import java.awt.*; +import java.util.List; -public class CategoryDistiller extends BlankRecipeCategory { - public static final String UID = "buildcraft:category_distiller"; +//public class CategoryDistiller extends BlankRecipeCategory +public class CategoryDistiller implements IRecipeCategory { + public static final ResourceLocation UID = new ResourceLocation(BCModules.FACTORY.getModId(), "category_distiller"); public static final ResourceLocation distillerBackground = new ResourceLocation("buildcraftfactory:textures/gui/distiller.png"); + private final IDrawable background; + private final IDrawable slot; + private final IDrawable fakeBackground; + + private final IDrawable icon; - private final IDrawable background, slot, fakeBackground; + private final IDrawableAnimated animated; - public CategoryDistiller(IGuiHelper helper) { - this.fakeBackground = helper.createBlankDrawable(76, 65); - this.background = helper.createDrawable(distillerBackground, 61, 12, 36, 57); - this.slot = helper.createDrawable(distillerBackground, 7, 34, 18, 18); + @OnlyIn(Dist.CLIENT) + private FontRenderer font = Minecraft.getInstance().font; + + public CategoryDistiller(IGuiHelper guiHelper) { +// this.fakeBackground = guiHelper.createBlankDrawable(76, 65); + this.fakeBackground = guiHelper.createBlankDrawable(90, 65); + this.background = guiHelper.createDrawable(distillerBackground, 61, 12, 36, 57); + this.slot = guiHelper.createDrawable(distillerBackground, 7, 34, 18, 18); + + this.icon = guiHelper.createDrawableIngredient(new ItemStack(BCFactoryBlocks.distiller.get())); + + IDrawableStatic overComplete = guiHelper.createDrawable(CategoryDistiller.distillerBackground, 212, 0, 36, 57); + this.animated = guiHelper.createAnimatedDrawable(overComplete, 40, IDrawableAnimated.StartDirection.LEFT, false); } @Override - public String getUid() { + public ResourceLocation getUid() { return UID; } @Override - public String getTitle() { - return "Distillable Fluids"; + public Class getRecipeClass() { + return IRefineryRecipeManager.IDistillationRecipe.class; } @Override + public String getTitle() { +// return new TextComponent("Distillable Fluids"); + return new TranslationTextComponent("buildcraft.jei.title.distillable_fluids").getString(); + } + public String getModName() { return BCModules.FACTORY.name(); } @Override public IDrawable getBackground() { - return fakeBackground; + return this.fakeBackground; } @Override - public void drawExtras(Minecraft minecraft) { - this.background.draw(minecraft, 20, 4); - this.slot.draw(minecraft, 0, 25); // -20, 21); - this.slot.draw(minecraft, 56, 0); // 36, -4); - this.slot.draw(minecraft, 56, 45); // 36, 41); + public IDrawable getIcon() { + return this.icon; } -// @Override -// public void drawAnimations(Minecraft minecraft) {} + @Override + public void setIngredients(IDistillationRecipe recipe, IIngredients ingredients) { + ingredients.setInput(VanillaTypes.FLUID, recipe.in()); + ingredients.setOutputs(VanillaTypes.FLUID, Lists.newArrayList(recipe.outGas(), recipe.outLiquid())); + } @Override - public void setRecipe(IRecipeLayout recipeLayout, WrapperDistiller recipeWrapper, IIngredients ingredients) { - IGuiFluidStackGroup guiFluidStacks = recipeLayout.getFluidStacks(); +// public void drawExtras(Minecraft minecraft) + public void draw(IRefineryRecipeManager.IDistillationRecipe recipe, MatrixStack stack, double mouseX, double mouseY) { + this.background.draw(stack, 20, 4); + this.slot.draw(stack, 0, 25); + this.slot.draw(stack, 56, 0); + this.slot.draw(stack, 56, 45); + + this.animated.draw(stack, 20, 4); + this.font.draw(stack, MjAPI.formatMj(recipe.powerRequired()) + " MJ", 58, 28, Color.CYAN.getRGB()); + } - guiFluidStacks.init(0, true, /*-19, 22*/ 1, 26, 16, 16, 10, false, null); - guiFluidStacks.set(0, ingredients.getInputs(FluidStack.class).get(0)); + @Override +// public void setRecipe(IRecipeLayout recipeLayout, WrapperDistiller recipeWrapper, IIngredients ingredients) + public void setRecipe(IRecipeLayout recipeLayout, IRefineryRecipeManager.IDistillationRecipe recipe, IIngredients ingredients) { + IGuiFluidStackGroup guiFluidStacks = recipeLayout.getFluidStacks(); + guiFluidStacks.init(0, true, 1, 26, 16, 16, 10, false, (IDrawable) null); +// guiFluidStacks.set(0, (List) ingredients.getInputs(FluidStack.class).get(0)); + guiFluidStacks.set(0, recipe.in()); + guiFluidStacks.init(1, false, 57, 1, 16, 16, 10, false, (IDrawable) null); +// guiFluidStacks.set(1, (List) ingredients.getOutputs(FluidStack.class).get(0)); + guiFluidStacks.set(1, recipe.outGas()); + guiFluidStacks.init(2, false, 57, 46, 16, 16, 10, false, (IDrawable) null); +// guiFluidStacks.set(2, (List) ingredients.getOutputs(FluidStack.class).get(1)); + guiFluidStacks.set(2, recipe.outLiquid()); + } - guiFluidStacks.init(1, false, /*37, -3*/ 57, 1, 16, 16, 10, false, null); - guiFluidStacks.set(1, ingredients.getOutputs(FluidStack.class).get(0)); + @Override + public List getTooltipStrings(IDistillationRecipe recipe, double mouseX, double mouseY) { + return Lists.newArrayList(); + } - guiFluidStacks.init(2, false, /*37, 42*/ 57, 46, 16, 16, 10, false, null); - guiFluidStacks.set(2, ingredients.getOutputs(FluidStack.class).get(1)); + @Override + public boolean handleClick(IRefineryRecipeManager.IDistillationRecipe recipe, double mouseX, double mouseY, int mouseButton) { + return false; } } diff --git a/common/buildcraft/compat/module/jei/factory/CategoryHeatable.java b/common/buildcraft/compat/module/jei/factory/CategoryHeatable.java index 75300fb..4b7d322 100644 --- a/common/buildcraft/compat/module/jei/factory/CategoryHeatable.java +++ b/common/buildcraft/compat/module/jei/factory/CategoryHeatable.java @@ -1,39 +1,76 @@ package buildcraft.compat.module.jei.factory; -import net.minecraft.client.Minecraft; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.fluids.FluidStack; import buildcraft.api.BCModules; -import mezz.jei.api.IGuiHelper; -import mezz.jei.api.gui.IDrawable; -import mezz.jei.api.gui.IGuiFluidStackGroup; +import buildcraft.api.recipes.IRefineryRecipeManager; +import buildcraft.api.recipes.IRefineryRecipeManager.IHeatableRecipe; +import buildcraft.factory.BCFactoryBlocks; +import buildcraft.lib.misc.StackUtil; +import com.google.common.collect.Lists; +import com.mojang.blaze3d.matrix.MatrixStack; +import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.gui.IRecipeLayout; +import mezz.jei.api.gui.drawable.IDrawable; +import mezz.jei.api.gui.drawable.IDrawableAnimated; +import mezz.jei.api.gui.drawable.IDrawableStatic; +import mezz.jei.api.gui.ingredient.IGuiFluidStackGroup; +import mezz.jei.api.helpers.IGuiHelper; import mezz.jei.api.ingredients.IIngredients; -import mezz.jei.api.recipe.BlankRecipeCategory; +import mezz.jei.api.recipe.category.IRecipeCategory; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TranslationTextComponent; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +import java.util.List; -public class CategoryHeatable extends BlankRecipeCategory { - public static final String UID = "buildcraft:category_heatable"; +//public class CategoryHeatable extends BlankRecipeCategory +public class CategoryHeatable implements IRecipeCategory { + public static final ResourceLocation UID = new ResourceLocation(BCModules.FACTORY.getModId(), "category_heatable"); public static final ResourceLocation energyHeaterBackground = new ResourceLocation("buildcraftfactory:textures/gui/energy_heater.png"); + private final IDrawable background; + private final IDrawable slotIn; + private final IDrawable slotOut; + + private final IDrawable icon; + + private final IDrawableAnimated animated; + - private final IDrawable background, slotIn, slotOut; + public CategoryHeatable(IGuiHelper guiHelper) { +// this.background = helper.createDrawable(energyHeaterBackground, 176, 19, 54, 19, 0, 0, 18, 80); + this.background = guiHelper.drawableBuilder(energyHeaterBackground, 176, 19, 54, 19).addPadding(0, 0, 18, 80).build(); + // Calen: top+1 to be at the same height as tubes of background +// this.slotIn = helper.createDrawable(energyHeaterBackground, 7, 22, 18, 18, 0, 0, 0, 0); +// this.slotIn = guiHelper.drawableBuilder(energyHeaterBackground, 7, 22, 18, 18).addPadding(0, 0, 0, 0).build(); + this.slotIn = guiHelper.drawableBuilder(energyHeaterBackground, 7, 22, 18, 18).addPadding(1, 0, 0, 0).build(); +// this.slotOut = helper.createDrawable(energyHeaterBackground, 7, 22, 18, 18, 0, 0, 72, 0); +// this.slotOut = guiHelper.drawableBuilder(energyHeaterBackground, 7, 22, 18, 18).addPadding(0, 0, 72, 0).build(); + this.slotOut = guiHelper.drawableBuilder(energyHeaterBackground, 7, 22, 18, 18).addPadding(1, 0, 72, 0).build(); - public CategoryHeatable(IGuiHelper helper) { - this.background = helper.createDrawable(energyHeaterBackground, 176, 19, 54, 19, 0, 0, 18, 80); - this.slotIn = helper.createDrawable(energyHeaterBackground, 7, 22, 18, 18, 0, 0, 0, 0); - this.slotOut = helper.createDrawable(energyHeaterBackground, 7, 22, 18, 18, 0, 0, 72, 0); + this.icon = guiHelper.createDrawableIngredient(new ItemStack(BCFactoryBlocks.heatExchange.get())); + + IDrawableStatic overComplete = guiHelper.createDrawable(CategoryHeatable.energyHeaterBackground, 176, 152, 54, 19); + this.animated = guiHelper.createAnimatedDrawable(overComplete, 40, IDrawableAnimated.StartDirection.LEFT, false); } @Override - public String getUid() { + public ResourceLocation getUid() { return UID; } @Override - public String getTitle() { - return "Heatable Fluids"; + public Class getRecipeClass() { + return IRefineryRecipeManager.IHeatableRecipe.class; } @Override + public String getTitle() { +// return new TextComponent("Heatable Fluids"); + return new TranslationTextComponent("buildcraft.jei.title.heatable_fluids").getString(); + } + public String getModName() { return BCModules.FACTORY.name(); } @@ -44,22 +81,47 @@ public IDrawable getBackground() { } @Override - public void drawExtras(Minecraft minecraft) { - slotIn.draw(minecraft); - slotOut.draw(minecraft); + public IDrawable getIcon() { + return this.icon; } -// @Override -// public void drawAnimations(Minecraft minecraft) {} + @Override + public void setIngredients(IHeatableRecipe recipe, IIngredients ingredients) { + ingredients.setInput(VanillaTypes.FLUID, recipe.in()); + ingredients.setOutput(VanillaTypes.FLUID, recipe.out() == null ? StackUtil.EMPTY_FLUID : recipe.out()); + } + + @OnlyIn(Dist.CLIENT) + @Override +// public void drawExtras(Minecraft minecraft) + public void draw(IRefineryRecipeManager.IHeatableRecipe recipe, MatrixStack stack, double mouseX, double mouseY) { + this.slotIn.draw(stack); + this.slotOut.draw(stack); + + this.animated.draw(stack, 18, 0); + } @Override - public void setRecipe(IRecipeLayout recipeLayout, WrapperHeatable recipeWrapper, IIngredients ingredients) { +// public void setRecipe(IRecipeLayout recipeLayout, WrapperHeatable recipeWrapper, IIngredients ingredients) + public void setRecipe(IRecipeLayout recipeLayout, IHeatableRecipe recipe, IIngredients ingredients) { IGuiFluidStackGroup guiFluidStacks = recipeLayout.getFluidStacks(); +// guiFluidStacks.init(0, true, 1, 1, 16, 16, 10, false, (IDrawable) null); + guiFluidStacks.init(0, true, 1, 2, 16, 16, 10, false, null); +// guiFluidStacks.set(0, (List) ingredients.getInputs(FluidStack.class).get(0)); + guiFluidStacks.set(0, recipe.in()); +// guiFluidStacks.init(1, false, 73, 1, 16, 16, 10, false, (IDrawable) null); + guiFluidStacks.init(1, false, 73, 2, 16, 16, 10, false, (IDrawable) null); +// guiFluidStacks.set(1, (List) ingredients.getOutputs(FluidStack.class).get(0)); + guiFluidStacks.set(1, recipe.out() == null ? StackUtil.EMPTY_FLUID : recipe.out()); + } - guiFluidStacks.init(0, true, 1, 1, 16, 16, 10, false, null); - guiFluidStacks.set(0, ingredients.getInputs(FluidStack.class).get(0)); + @Override + public List getTooltipStrings(IHeatableRecipe recipe, double mouseX, double mouseY) { + return Lists.newArrayList(); + } - guiFluidStacks.init(1, false, 73, 1, 16, 16, 10, false, null); - guiFluidStacks.set(1, ingredients.getOutputs(FluidStack.class).get(0)); + @Override + public boolean handleClick(IRefineryRecipeManager.IHeatableRecipe recipe, double mouseX, double mouseY, int mouseButton) { + return false; } } diff --git a/common/buildcraft/compat/module/jei/factory/HandlerCoolable.java b/common/buildcraft/compat/module/jei/factory/HandlerCoolable.java deleted file mode 100644 index a2fa129..0000000 --- a/common/buildcraft/compat/module/jei/factory/HandlerCoolable.java +++ /dev/null @@ -1,15 +0,0 @@ -package buildcraft.compat.module.jei.factory; - -import buildcraft.api.recipes.IRefineryRecipeManager; - -import buildcraft.compat.module.jei.BCPluginJEI; - -import mezz.jei.api.recipe.IRecipeWrapper; -import mezz.jei.api.recipe.IRecipeWrapperFactory; - -public class HandlerCoolable implements IRecipeWrapperFactory { - @Override - public IRecipeWrapper getRecipeWrapper(IRefineryRecipeManager.ICoolableRecipe recipe) { - return new WrapperCoolable(BCPluginJEI.registry.getJeiHelpers().getGuiHelper(), recipe); - } -} diff --git a/common/buildcraft/compat/module/jei/factory/HandlerDistiller.java b/common/buildcraft/compat/module/jei/factory/HandlerDistiller.java deleted file mode 100644 index a510139..0000000 --- a/common/buildcraft/compat/module/jei/factory/HandlerDistiller.java +++ /dev/null @@ -1,15 +0,0 @@ -package buildcraft.compat.module.jei.factory; - -import buildcraft.api.recipes.IRefineryRecipeManager; - -import buildcraft.compat.module.jei.BCPluginJEI; - -import mezz.jei.api.recipe.IRecipeWrapper; -import mezz.jei.api.recipe.IRecipeWrapperFactory; - -public class HandlerDistiller implements IRecipeWrapperFactory { - @Override - public IRecipeWrapper getRecipeWrapper(IRefineryRecipeManager.IDistillationRecipe recipe) { - return new WrapperDistiller(BCPluginJEI.registry.getJeiHelpers().getGuiHelper(), recipe); - } -} diff --git a/common/buildcraft/compat/module/jei/factory/HandlerHeatable.java b/common/buildcraft/compat/module/jei/factory/HandlerHeatable.java deleted file mode 100644 index 0fbb251..0000000 --- a/common/buildcraft/compat/module/jei/factory/HandlerHeatable.java +++ /dev/null @@ -1,15 +0,0 @@ -package buildcraft.compat.module.jei.factory; - -import buildcraft.api.recipes.IRefineryRecipeManager; - -import buildcraft.compat.module.jei.BCPluginJEI; - -import mezz.jei.api.recipe.IRecipeWrapper; -import mezz.jei.api.recipe.IRecipeWrapperFactory; - -public class HandlerHeatable implements IRecipeWrapperFactory { - @Override - public IRecipeWrapper getRecipeWrapper(IRefineryRecipeManager.IHeatableRecipe recipe) { - return new WrapperHeatable(BCPluginJEI.registry.getJeiHelpers().getGuiHelper(), recipe); - } -} diff --git a/common/buildcraft/compat/module/jei/factory/WrapperCoolable.java b/common/buildcraft/compat/module/jei/factory/WrapperCoolable.java deleted file mode 100644 index 518ae0d..0000000 --- a/common/buildcraft/compat/module/jei/factory/WrapperCoolable.java +++ /dev/null @@ -1,86 +0,0 @@ -package buildcraft.compat.module.jei.factory; - -import java.util.List; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; -import net.minecraft.client.Minecraft; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; -import buildcraft.api.recipes.IRefineryRecipeManager; -import mezz.jei.api.IGuiHelper; -import mezz.jei.api.gui.IDrawableAnimated; -import mezz.jei.api.gui.IDrawableStatic; -import mezz.jei.api.ingredients.IIngredients; -import mezz.jei.api.recipe.IRecipeWrapper; - -public class WrapperCoolable implements IRecipeWrapper { - private final IRefineryRecipeManager.ICoolableRecipe recipe; - private final ImmutableList in, out; - private final IDrawableAnimated animatedCooling, animatedHeating; - - WrapperCoolable(IGuiHelper guiHelper, IRefineryRecipeManager.ICoolableRecipe recipe) { - this.recipe = recipe; - this.in = ImmutableList.of(recipe.in()); - //noinspection ConstantConditions - this.out = (recipe.out() != null) ? ImmutableList.of(recipe.out()) : ImmutableList.of(); - - IDrawableStatic overComplete = guiHelper.createDrawable(CategoryCoolable.heatExchangerBackground, 52, 171, 54, 17); - this.animatedCooling = guiHelper.createAnimatedDrawable(overComplete, /*recipe.ticks() * 20*/ 40, IDrawableAnimated.StartDirection.LEFT, false); - overComplete = guiHelper.createDrawable(CategoryCoolable.heatExchangerBackground, 52, 188, 54, 17); - this.animatedHeating = guiHelper.createAnimatedDrawable(overComplete, /*recipe.ticks() * 20*/ 40, IDrawableAnimated.StartDirection.RIGHT, false); - } - -// @Override -// public List getInputs() { -// return Collections.emptyList(); -// } -// -// @Override -// public List getOutputs() { -// return Collections.emptyList(); -// } -// -// @Override -// public List getFluidInputs() { -// return in; -// } -// -// @Override -// public List getFluidOutputs() { -// return out; -// } -// -// @Override -// public void drawInfo(Minecraft minecraft, int recipeWidth, int recipeHeight) {} - - @Override - public void getIngredients(IIngredients ingredients) { - ingredients.setInputs(FluidStack.class, this.in); - ingredients.setOutputs(FluidStack.class, this.out); - } - - @Override - @SideOnly(Side.CLIENT) - public void drawInfo(Minecraft minecraft, int recipeWidth, int recipeHeight, int mouseX, int mouseY) { - this.animatedCooling.draw(minecraft, 18, 0); - this.animatedHeating.draw(minecraft, 18, 0); - // minecraft.fontRenderer.drawString("Takes " + (recipe.ticks() / 20.0) + "s", 93, 0, Color.gray.getRGB()); - } - -// @Override -// public void drawAnimations(Minecraft minecraft, int recipeWidth, int recipeHeight) { -// animatedCooling.draw(minecraft, 18, 0); -// animatedHeating.draw(minecraft, 18, 0); -// } - - @Override - public List getTooltipStrings(int mouseX, int mouseY) { - return Lists.newArrayList(); - } - - @Override - public boolean handleClick(Minecraft minecraft, int mouseX, int mouseY, int mouseButton) { - return false; - } -} diff --git a/common/buildcraft/compat/module/jei/factory/WrapperDistiller.java b/common/buildcraft/compat/module/jei/factory/WrapperDistiller.java deleted file mode 100644 index 0c4b316..0000000 --- a/common/buildcraft/compat/module/jei/factory/WrapperDistiller.java +++ /dev/null @@ -1,84 +0,0 @@ -package buildcraft.compat.module.jei.factory; - -import java.awt.Color; -import java.util.List; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; -import net.minecraft.client.Minecraft; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; -import buildcraft.api.mj.MjAPI; -import buildcraft.api.recipes.IRefineryRecipeManager; -import mezz.jei.api.IGuiHelper; -import mezz.jei.api.gui.IDrawableAnimated; -import mezz.jei.api.gui.IDrawableStatic; -import mezz.jei.api.ingredients.IIngredients; -import mezz.jei.api.recipe.IRecipeWrapper; - -public class WrapperDistiller implements IRecipeWrapper { - public final IRefineryRecipeManager.IDistillationRecipe recipe; - private final ImmutableList in, out; - private final IDrawableAnimated animated; - - WrapperDistiller(IGuiHelper guiHelper, IRefineryRecipeManager.IDistillationRecipe recipe) { - this.recipe = recipe; - this.in = ImmutableList.of(recipe.in()); - this.out = ImmutableList.of(recipe.outGas(), recipe.outLiquid()); - - IDrawableStatic overComplete = guiHelper.createDrawable(CategoryDistiller.distillerBackground, 212, 0, 36, 57); - this.animated = guiHelper.createAnimatedDrawable(overComplete, /*recipe.ticks() * 20*/ 40, IDrawableAnimated.StartDirection.LEFT, false); - } - -// @Override -// public List getInputs() { -// return Collections.emptyList(); -// } -// -// @Override -// public List getOutputs() { -// return Collections.emptyList(); -// } -// -// @Override -// public List getFluidInputs() { -// return in; -// } -// -// @Override -// public List getFluidOutputs() { -// return out; -// } -// -// @Override -// public void drawInfo(Minecraft minecraft, int recipeWidth, int recipeHeight) {} - - - @Override - public void getIngredients(IIngredients ingredients) { - ingredients.setInputs(FluidStack.class, this.in); - ingredients.setOutputs(FluidStack.class, this.out); - } - - @Override - @SideOnly(Side.CLIENT) - public void drawInfo(Minecraft minecraft, int recipeWidth, int recipeHeight, int mouseX, int mouseY) { - this.animated.draw(minecraft, 20, 4); - minecraft.fontRenderer.drawString(MjAPI.formatMj(recipe.powerRequired()) + " MJ", 58, 28, Color.CYAN.getRGB()); - } - -// @Override -// public void drawAnimations(Minecraft minecraft, int recipeWidth, int recipeHeight) { -// animated.draw(minecraft, 0, 0); -// } - - @Override - public List getTooltipStrings(int mouseX, int mouseY) { - return Lists.newArrayList(); - } - - @Override - public boolean handleClick(Minecraft minecraft, int mouseX, int mouseY, int mouseButton) { - return false; - } -} diff --git a/common/buildcraft/compat/module/jei/factory/WrapperHeatable.java b/common/buildcraft/compat/module/jei/factory/WrapperHeatable.java deleted file mode 100644 index 593aed0..0000000 --- a/common/buildcraft/compat/module/jei/factory/WrapperHeatable.java +++ /dev/null @@ -1,84 +0,0 @@ -package buildcraft.compat.module.jei.factory; - -import java.util.List; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; -import net.minecraft.client.Minecraft; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; -import buildcraft.api.recipes.IRefineryRecipeManager; -import mezz.jei.api.IGuiHelper; -import mezz.jei.api.gui.IDrawableAnimated; -import mezz.jei.api.gui.IDrawableStatic; -import mezz.jei.api.ingredients.IIngredients; -import mezz.jei.api.recipe.IRecipeWrapper; - -public class WrapperHeatable implements IRecipeWrapper { - private final IRefineryRecipeManager.IHeatableRecipe heatable; - private final ImmutableList in, out; - private final IDrawableAnimated animated; - - public WrapperHeatable(IGuiHelper guiHelper, IRefineryRecipeManager.IHeatableRecipe recipe) { - this.heatable = recipe; - this.in = ImmutableList.of(recipe.in()); - //noinspection ConstantConditions - this.out = (recipe.out() != null) ? ImmutableList.of(recipe.out()) : ImmutableList.of(); - - IDrawableStatic overComplete = guiHelper.createDrawable(CategoryHeatable.energyHeaterBackground, 176, 152, 54, 19); - animated = guiHelper.createAnimatedDrawable(overComplete, /*recipe.ticks() * 20*/ 40, IDrawableAnimated.StartDirection.LEFT, false); - } - -// @Override -// public List getInputs() { -// return Collections.emptyList(); -// } -// -// @Override -// public List getOutputs() { -// return Collections.emptyList(); -// } -// -// @Override -// public List getFluidInputs() { -// return in; -// } -// -// @Override -// public List getFluidOutputs() { -// return out; -// } -// -// @Override -// public void drawInfo(Minecraft minecraft, int recipeWidth, int recipeHeight) {} - - @Override - public void getIngredients(IIngredients ingredients) { - ingredients.setInputs(FluidStack.class, this.in); - ingredients.setOutputs(FluidStack.class, this.out); - } - - @Override - @SideOnly(Side.CLIENT) - public void drawInfo(Minecraft minecraft, int recipeWidth, int recipeHeight, int mouseX, int mouseY) { - this.animated.draw(minecraft, 18, 0); -// minecraft.fontRenderer.drawString("Takes " + (heatable.ticks() / 20.0) + "s", 93, 0, Color.gray.getRGB()); -// int rftick = Math.abs(heatable.heatFrom() - heatable.heatTo()) * BuildCraftFactory.rfPerHeatPerMB * heatable.in().amount; -// minecraft.fontRenderer.drawString(" at " + rftick + "RF/t", 93, 11, Color.gray.getRGB()); - } - -// @Override -// public void drawAnimations(Minecraft minecraft, int recipeWidth, int recipeHeight) { -// animated.draw(minecraft, 18, 0); -// } - - @Override - public List getTooltipStrings(int mouseX, int mouseY) { - return Lists.newArrayList(); - } - - @Override - public boolean handleClick(Minecraft minecraft, int mouseX, int mouseY, int mouseButton) { - return false; - } -} diff --git a/common/buildcraft/compat/module/jei/factory/package-info.java b/common/buildcraft/compat/module/jei/factory/package-info.java index 04b20ee..b208342 100644 --- a/common/buildcraft/compat/module/jei/factory/package-info.java +++ b/common/buildcraft/compat/module/jei/factory/package-info.java @@ -2,5 +2,6 @@ @MethodsReturnNonnullByDefault package buildcraft.compat.module.jei.factory; +import mezz.jei.api.MethodsReturnNonnullByDefault; + import javax.annotation.ParametersAreNonnullByDefault; -import mcp.MethodsReturnNonnullByDefault; diff --git a/common/buildcraft/compat/module/jei/gui/GuiHandlerBuildCraft.java b/common/buildcraft/compat/module/jei/gui/GuiHandlerBuildCraft.java new file mode 100644 index 0000000..b96e850 --- /dev/null +++ b/common/buildcraft/compat/module/jei/gui/GuiHandlerBuildCraft.java @@ -0,0 +1,46 @@ +package buildcraft.compat.module.jei.gui; + +import buildcraft.lib.gui.GuiBC8; +import buildcraft.lib.gui.IGuiElement; +import buildcraft.lib.gui.pos.GuiRectangle; +import mezz.jei.api.gui.handlers.IGuiContainerHandler; +import net.minecraft.client.renderer.Rectangle2d; +import net.minecraft.util.math.MathHelper; + +import javax.annotation.Nonnull; +import java.util.ArrayList; +import java.util.List; + +public class GuiHandlerBuildCraft implements IGuiContainerHandler> { + @Nonnull + @Override + public List getGuiExtraAreas(GuiBC8 guiDirty) { + List list = new ArrayList<>(); + + for (IGuiElement element : guiDirty.mainGui.shownElements) { + GuiRectangle rect = element.asImmutable(); + int x = (int) rect.x; + int y = (int) rect.y; + int endX = MathHelper.ceil(rect.getEndX()); + int endY = MathHelper.ceil(rect.getEndY()); + int width = endX - x; + int height = endY - y; + list.add(new Rectangle2d(x, y, width, height)); + } + + return list; + } + + +// @Nullable +// @Override +// public Object getIngredientUnderMouse(GuiBC8 screen, double mouseX, double mouseY) { +// return screen.getIngredientUnderMouse(mouseX, mouseY); +// } + +// @NotNull +// @Override +// public Collection getGuiClickableAreas(GuiBC8 screen, double mouseX, double mouseY) { +// return Collections.emptyList(); +// } +} diff --git a/common/buildcraft/compat/module/jei/recipe/GateGuiHandler.java b/common/buildcraft/compat/module/jei/recipe/GateGuiHandler.java deleted file mode 100644 index bb27224..0000000 --- a/common/buildcraft/compat/module/jei/recipe/GateGuiHandler.java +++ /dev/null @@ -1,37 +0,0 @@ -package buildcraft.compat.module.jei.recipe; -//package buildcraft.compat.module.jei; -// -//import java.awt.Rectangle; -//import java.util.ArrayList; -//import java.util.List; -// -//import buildcraft.transport.gui.GuiGateInterface; -// -//import mezz.jei.api.gui.IAdvancedGuiHandler; -// -//public class GateGuiHandler implements IAdvancedGuiHandler { -// @Override -// public Class getGuiContainerClass() { -// return GuiGateInterface.class; -// } -// -// @Override -// public List getGuiExtraAreas(GuiGateInterface gate) { -// List rectangles = new ArrayList<>(); -// int guiLeft = (gate.width - gate.xSize()) / 2; -// int guiTop = (gate.height - gate.ySize()) / 2; -// -// // Actions -// int actionStartX = guiLeft + gate.xSize(); -// int actionStartY = guiTop + 6; -// -// if (gate.actionRows > 1) { -// int endRow = gate.actionRows * 18; -// rectangles.add(new Rectangle(actionStartX, actionStartY, 6 * 18, endRow)); -// rectangles.add(new Rectangle(actionStartX, actionStartY + endRow, gate.lastActionRowSize, 18)); -// } else if (gate.actionRows == 1) { -// rectangles.add(new Rectangle(actionStartX, actionStartY, gate.lastActionRowSize, 18)); -// } -// return rectangles; -// } -//} diff --git a/common/buildcraft/compat/module/jei/recipe/GuiHandlerBuildCraft.java b/common/buildcraft/compat/module/jei/recipe/GuiHandlerBuildCraft.java deleted file mode 100644 index f6a434d..0000000 --- a/common/buildcraft/compat/module/jei/recipe/GuiHandlerBuildCraft.java +++ /dev/null @@ -1,51 +0,0 @@ -package buildcraft.compat.module.jei.recipe; - -import java.awt.Rectangle; -import java.util.ArrayList; -import java.util.List; - -import javax.annotation.Nullable; - -import net.minecraft.util.math.MathHelper; - -import buildcraft.lib.gui.GuiBC8; -import buildcraft.lib.gui.IGuiElement; -import buildcraft.lib.gui.pos.GuiRectangle; - -import mezz.jei.api.gui.IAdvancedGuiHandler; - -public class GuiHandlerBuildCraft implements IAdvancedGuiHandler { - - @Override - public Class getGuiContainerClass() { - return GuiBC8.class; - } - - @Override - @Nullable - public List getGuiExtraAreas(GuiBC8 guiDirty) { - GuiBC8 gui = guiDirty; - // Get the rectangles of everything that is *outside* the main gui area - List list = new ArrayList<>(); - for (IGuiElement element : gui.mainGui.shownElements) { - // Ignore children: all ledger style elements are top level - GuiRectangle rect = element.asImmutable(); -// if (!gui.rootElement.contains(rect)) { - // Round down x and y - int x = (int) rect.x; - int y = (int) rect.y; - // Round up width and height - int endX = MathHelper.ceil(rect.getEndX()); - int endY = MathHelper.ceil(rect.getEndY()); - int width = endX - x; - int height = endY - y; - list.add(new Rectangle(x, y, width, height)); -// } - } - if (list.isEmpty()) { - // Cheapen JEI checks a tiny bit. Possibly. - return null; - } - return list; - } -} diff --git a/common/buildcraft/compat/module/jei/recipe/HandlerFlexibleRecipe.java b/common/buildcraft/compat/module/jei/recipe/HandlerFlexibleRecipe.java deleted file mode 100644 index 1454d01..0000000 --- a/common/buildcraft/compat/module/jei/recipe/HandlerFlexibleRecipe.java +++ /dev/null @@ -1,15 +0,0 @@ -package buildcraft.compat.module.jei.recipe; -//package buildcraft.compat.module.jei.recipe; -// -//import buildcraft.api.recipes.IFlexibleRecipe; -// -//import javax.annotation.Nonnull; -//import mezz.jei.api.recipe.IRecipeHandler; -// -//public abstract class HandlerFlexibleRecipe implements IRecipeHandler { -// @Nonnull -// @Override -// public Class getRecipeClass() { -// return IFlexibleRecipe.class; -// } -//} diff --git a/common/buildcraft/compat/module/jei/recipe/LedgerGuiHandler.java b/common/buildcraft/compat/module/jei/recipe/LedgerGuiHandler.java deleted file mode 100644 index 7624e92..0000000 --- a/common/buildcraft/compat/module/jei/recipe/LedgerGuiHandler.java +++ /dev/null @@ -1,35 +0,0 @@ -package buildcraft.compat.module.jei.recipe; -//package buildcraft.compat.module.jei; -// -//import java.awt.Rectangle; -//import java.util.ArrayList; -//import java.util.List; -// -//import buildcraft.core.lib.gui.GuiBuildCraft; -//import buildcraft.core.lib.gui.Ledger; -// -//import mezz.jei.api.gui.IAdvancedGuiHandler; -// -//public class LedgerGuiHandler implements IAdvancedGuiHandler { -// @Override -// public Class getGuiContainerClass() { -// return GuiBuildCraft.class; -// } -// -// @Override -// public List getGuiExtraAreas(GuiBuildCraft gui) { -// List rectangles = new ArrayList<>(); -// int guiLeft = (gui.width - gui.xSize()) / 2; -// int guiTop = (gui.height - gui.ySize()) / 2; -// -// int yPos = 8; -// for (Ledger l : gui.ledgerManager.getAll()) { -// if (l.isVisible()) { -// rectangles.add(new Rectangle(guiLeft + gui.xSize(), guiTop + yPos, l.getWidth(), l.getHeight())); -// yPos += l.getHeight(); -// } -// } -// -// return rectangles; -// } -//} diff --git a/common/buildcraft/compat/module/jei/silicon/CategoryAssemblyTable.java b/common/buildcraft/compat/module/jei/silicon/CategoryAssemblyTable.java index 701b365..98b7a67 100644 --- a/common/buildcraft/compat/module/jei/silicon/CategoryAssemblyTable.java +++ b/common/buildcraft/compat/module/jei/silicon/CategoryAssemblyTable.java @@ -1,68 +1,145 @@ package buildcraft.compat.module.jei.silicon; -import java.util.List; - -import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; - import buildcraft.api.BCModules; - -import mezz.jei.api.IGuiHelper; -import mezz.jei.api.gui.IDrawable; -import mezz.jei.api.gui.IGuiItemStackGroup; +import buildcraft.api.mj.MjAPI; +import buildcraft.api.recipes.IAssemblyRecipe; +import buildcraft.api.recipes.IngredientStack; +import buildcraft.silicon.BCSiliconBlocks; +import com.google.common.collect.Lists; +import com.mojang.blaze3d.matrix.MatrixStack; +import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.gui.IRecipeLayout; +import mezz.jei.api.gui.drawable.IDrawable; +import mezz.jei.api.gui.drawable.IDrawableAnimated; +import mezz.jei.api.gui.drawable.IDrawableStatic; +import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; +import mezz.jei.api.helpers.IGuiHelper; import mezz.jei.api.ingredients.IIngredients; -import mezz.jei.api.recipe.IRecipeCategory; +import mezz.jei.api.recipe.category.IRecipeCategory; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.text.TranslationTextComponent; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; -public class CategoryAssemblyTable implements IRecipeCategory { - public static final String UID = "buildcraft-compat:silicon.assembly"; +import java.awt.*; +import java.util.List; +import java.util.*; +import java.util.stream.Collectors; - protected final ResourceLocation backgroundLocation; +public class CategoryAssemblyTable implements IRecipeCategory { + // public static final ResourceLocation UID = new ResourceLocation("buildcraft-compat:silicon.assembly"); + public static final ResourceLocation UID = new ResourceLocation(BCModules.SILICON.getModId(), "assembly"); + protected final ResourceLocation backgroundLocation = new ResourceLocation("buildcraftsilicon", "textures/gui/assembly_table.png"); private final IDrawable background; - public CategoryAssemblyTable(IGuiHelper guiHelper) { - this.backgroundLocation = new ResourceLocation("buildcraftsilicon", "textures/gui/assembly_table.png"); - this.background = guiHelper.createDrawable(backgroundLocation, 5, 34, 166, 76, 10, 0, 0, 0); + private final IDrawable icon; + + private final Map progressBarMap = new HashMap<>(); + private final Map> inputsMap = new HashMap<>(); + private final Map outputsMap = new HashMap<>(); + + @OnlyIn(Dist.CLIENT) + private FontRenderer font = Minecraft.getInstance().font; + + // public CategoryAssemblyTable(IGuiHelper guiHelper, AssemblyRecipeBasic recipe) + public CategoryAssemblyTable(IGuiHelper guiHelper, Collection recipes) { +// this.background = guiHelper.createDrawable(this.backgroundLocation, 5, 34, 166, 76, 10, 0, 0, 0); + this.background = guiHelper.drawableBuilder(this.backgroundLocation, 5, 34, 166, 76).addPadding(10, 0, 0, 0).build(); + + this.icon = guiHelper.createDrawableIngredient(new ItemStack(BCSiliconBlocks.assemblyTable.get())); + + ResourceLocation backgroundLocation = new ResourceLocation("buildcraftsilicon", "textures/gui/assembly_table.png"); +// IDrawableStatic progressDrawable = guiHelper.createDrawable(backgroundLocation, 176, 48, 4, 71, 10, 0, 0, 0); + IDrawableStatic progressDrawable = guiHelper.drawableBuilder(backgroundLocation, 176, 48, 4, 71).addPadding(10, 0, 0, 0).build(); + + for (IAssemblyRecipe recipe : recipes) { + List _inputs = Lists.newArrayList(); + + for (IngredientStack in : recipe.getInputsFor(ItemStack.EMPTY)) { + List inner = new ArrayList(); + + for (ItemStack matching : in.ingredient.getItems()) { + matching = matching.copy(); + matching.setCount(in.count); + inner.add(matching); + } + + _inputs.add(Ingredient.of(inner.stream())); + } + + this.inputsMap.put(recipe, _inputs); + this.outputsMap.put(recipe, Ingredient.of(recipe.getOutputPreviews().stream())); + + long mj = recipe.getRequiredMicroJoulesFor(ItemStack.EMPTY); +// this.progressBar = guiHelper.createAnimatedDrawable(progressDrawable, (int) Math.max(10L, mj / MjAPI.MJ / 50L), IDrawableAnimated.StartDirection.BOTTOM, false); + progressBarMap.put(recipe, guiHelper.createAnimatedDrawable(progressDrawable, (int) Math.max(10L, mj / MjAPI.MJ / 50L), IDrawableAnimated.StartDirection.BOTTOM, false)); + } } @Override - public String getUid() { + public ResourceLocation getUid() { return UID; } @Override - public String getTitle() { - return "Assembly Table"; + public Class getRecipeClass() { + return IAssemblyRecipe.class; } @Override + public String getTitle() { +// return new TextComponent("Assembly Table"); + return new TranslationTextComponent("tile.assemblyTableBlock.name").getString(); + } + public String getModName() { return BCModules.SILICON.name(); } @Override public IDrawable getBackground() { - return background; + return this.background; + } + + @Override + public IDrawable getIcon() { + return this.icon; + } + + @Override + public void setIngredients(IAssemblyRecipe recipe, IIngredients ingredients) { + ingredients.setInputIngredients(recipe.getRequiredIngredientStacks().stream().map(is -> is.ingredient).collect(Collectors.toList())); + ingredients.setOutputs(VanillaTypes.ITEM, Lists.newArrayList(recipe.getOutput())); + } + + @OnlyIn(Dist.CLIENT) + @Override + public void draw(IAssemblyRecipe recipe, MatrixStack stack, double mouseX, double mouseY) { +// this.progressBar.draw(stack, 81, 2); + this.progressBarMap.get(recipe).draw(stack, 81, 2); + long mj = recipe.getRequiredMicroJoulesFor(ItemStack.EMPTY); + this.font.draw(stack, MjAPI.formatMj(mj) + " MJ", 4, 0, Color.gray.getRGB()); } @Override - public void setRecipe(IRecipeLayout recipeLayout, WrapperAssemblyTable recipeWrapper, IIngredients ingredients) { +// public void setRecipe(IRecipeLayout recipeLayout, WrapperAssemblyTable recipeWrapper, IIngredients ingredients) + public void setRecipe(IRecipeLayout recipeLayout, IAssemblyRecipe recipe, IIngredients ingredients) { IGuiItemStackGroup guiItemStacks = recipeLayout.getItemStacks(); - List> inputs = ingredients.getInputs(ItemStack.class); - for (int i = 0; i < inputs.size(); i++) { - guiItemStacks.init(i, true, 2 + (i % 3) * 18, 11 + (i / 3) * 18); + List> inputs = ingredients.getInputs(VanillaTypes.ITEM); + // Calen: the looks moved x-1 y-1 off the slot in 1.18.2 with the position used in 1.12.2 + for (int i = 0; i < inputs.size(); ++i) { + guiItemStacks.init(i, true, 2 + i % 3 * 18, 11 + i / 3 * 18); guiItemStacks.set(i, inputs.get(i)); -// Object o = recipeWrapper.getInputs().get(i); -// if (o instanceof ItemStack) { -// guiItemStacks.set(i, (ItemStack) o); -// } else if (o instanceof List) { -// guiItemStacks.set(i, (List) o); -// } } guiItemStacks.init(12, false, 110, 11); - guiItemStacks.set(12, ingredients.getOutputs(ItemStack.class).get(0)); +// guiItemStacks.set(12, (List) ingredients.getOutputs(ItemStack.class).get(0)); + guiItemStacks.set(12, ingredients.getOutputs(VanillaTypes.ITEM).get(0)); } } diff --git a/common/buildcraft/compat/module/jei/silicon/CategoryIntegrationTable.java b/common/buildcraft/compat/module/jei/silicon/CategoryIntegrationTable.java index ffe1d16..61ddfe3 100644 --- a/common/buildcraft/compat/module/jei/silicon/CategoryIntegrationTable.java +++ b/common/buildcraft/compat/module/jei/silicon/CategoryIntegrationTable.java @@ -1,77 +1,130 @@ package buildcraft.compat.module.jei.silicon; -import java.util.List; - -import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; - import buildcraft.api.BCModules; - -import mezz.jei.api.IGuiHelper; -import mezz.jei.api.gui.IDrawable; -import mezz.jei.api.gui.IGuiItemStackGroup; +import buildcraft.api.mj.MjAPI; +import buildcraft.api.recipes.IntegrationRecipe; +import buildcraft.silicon.BCSiliconBlocks; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import com.mojang.blaze3d.matrix.MatrixStack; +import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.gui.IRecipeLayout; +import mezz.jei.api.gui.drawable.IDrawable; +import mezz.jei.api.gui.drawable.IDrawableAnimated; +import mezz.jei.api.gui.drawable.IDrawableStatic; +import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; +import mezz.jei.api.helpers.IGuiHelper; import mezz.jei.api.ingredients.IIngredients; -import mezz.jei.api.recipe.IRecipeCategory; +import mezz.jei.api.recipe.category.IRecipeCategory; +import net.minecraft.block.Blocks; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.text.TranslationTextComponent; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; -public class CategoryIntegrationTable implements IRecipeCategory { - public static final String UID = "buildcraft-compat:silicon.integration"; +import java.awt.*; +import java.util.List; +import java.util.stream.Collectors; - protected final ResourceLocation backgroundLocation; +//public class CategoryIntegrationTable implements IRecipeCategory +public class CategoryIntegrationTable implements IRecipeCategory { + // public static final ResourceLocation UID = new ResourceLocation("buildcraft-compat:silicon.integration"); + public static final ResourceLocation UID = new ResourceLocation(BCModules.SILICON.getModId(), "integration"); + protected final ResourceLocation backgroundLocation = new ResourceLocation("buildcraftsilicon", "textures/gui/integration_table.png"); private final IDrawable background; - private WrapperIntegrationTable wrapper = null; - public CategoryIntegrationTable(IGuiHelper guiHelper) { - backgroundLocation = new ResourceLocation("buildcraftsilicon", "textures/gui/integration_table.png"); - background = guiHelper.createDrawable(backgroundLocation, 17, 22, 153, 71, 0, 0, 9, 0); + private final IDrawable icon; + + private final IntegrationRecipe recipe; + private final IDrawableAnimated progressBar; + private final List inputs; + private final List outputs; + + @OnlyIn(Dist.CLIENT) + private FontRenderer font = Minecraft.getInstance().font; + + public CategoryIntegrationTable(IGuiHelper guiHelper, IntegrationRecipe recipe) { +// this.background = guiHelper.createDrawable(this.backgroundLocation, 17, 22, 153, 71, 0, 0, 9, 0); + this.background = guiHelper.drawableBuilder(this.backgroundLocation, 17, 22, 153, 71).addPadding(0, 0, 9, 0).build(); + + this.icon = guiHelper.createDrawableIngredient(new ItemStack(BCSiliconBlocks.integrationTable.get())); + + this.recipe = recipe; + // Calen: not impl in 1.12.2 + List inputs = Lists.newArrayList(); + this.inputs = ImmutableList.copyOf(inputs); + this.outputs = ImmutableList.of(new ItemStack(Blocks.COBBLESTONE)); + ResourceLocation backgroundLocation = new ResourceLocation("buildcraftsilicon", "textures/gui/integration_table.png"); +// IDrawableStatic progressDrawable = guiHelper.createDrawable(backgroundLocation, 176, 17, 4, 69, 0, 0, 0, 0); + IDrawableStatic progressDrawable = guiHelper.drawableBuilder(this.backgroundLocation, 176, 17, 4, 69).addPadding(0, 0, 0, 0).build(); + this.progressBar = guiHelper.createAnimatedDrawable(progressDrawable, 720, IDrawableAnimated.StartDirection.BOTTOM, false); } - @Override - public String getUid() { + public ResourceLocation getUid() { return UID; } @Override + public Class getRecipeClass() { + return IntegrationRecipe.class; + } + public String getTitle() { - return "Integration Table"; +// return new TextComponent("Integration Table"); + return new TranslationTextComponent("tile.integrationTableBlock.name").getString(); } - @Override public String getModName() { return BCModules.SILICON.name(); } - @Override public IDrawable getBackground() { - return background; + return this.background; } @Override - public void setRecipe(IRecipeLayout recipeLayout, WrapperIntegrationTable recipeWrapper, IIngredients ingredients) { - IGuiItemStackGroup guiItemStacks = recipeLayout.getItemStacks(); + public IDrawable getIcon() { + return this.icon; + } + + @Override + public void setIngredients(IntegrationRecipe recipe, IIngredients ingredients) { + ingredients.setInputIngredients(recipe.getRequirements().stream().map(is -> is.ingredient).collect(Collectors.toList())); + ingredients.setOutput(VanillaTypes.ITEM, recipe.getOutput()); + } + - List> inputs = ingredients.getInputs(ItemStack.class); + @OnlyIn(Dist.CLIENT) + @Override + public void draw(IntegrationRecipe recipe, MatrixStack stack, double mouseX, double mouseY) { + this.progressBar.draw(stack, 156, 1); + this.font.draw(stack, MjAPI.formatMj(0L) + " MJ", 80, 52, Color.gray.getRGB()); + + } + + @Override + // public void setRecipe(IRecipeLayout recipeLayout, WrapperIntegrationTable recipeWrapper, IIngredients ingredients) + public void setRecipe(IRecipeLayout recipeLayout, IntegrationRecipe recipe, IIngredients ingredients) { + IGuiItemStackGroup guiItemStacks = recipeLayout.getItemStacks(); +// List> inputs = ingredients.getInputs(ItemStack.class); + List> inputs = ingredients.getInputs(VanillaTypes.ITEM); int inventoryIndex = 0; + for (int y = 0; y < 3; ++y) { for (int x = 0; x < 3; ++x) { - int slotIndex = ((x == 1) && (y == 1)) ? 0 : (x + y * 3 + 1); + int slotIndex = x == 1 && y == 1 ? 0 : x + y * 3 + 1; if (inputs.size() > slotIndex) { guiItemStacks.init(inventoryIndex, true, 19 + x * 25, 24 + y * 25); guiItemStacks.set(inventoryIndex, inputs.get(slotIndex)); inventoryIndex++; } - // this.addSlotToContainer(new SlotBase(x == 1 && y == 1 ? tile.invTarget : tile.invToIntegrate, indexes[x + y * 3], 19 + x * 25, 24 + y * 25)); } } -// for (int i = 0; i < wrapper.getInputs().size(); i++) { -// int x = ContainerIntegrationTable.SLOT_X[i] - 9; -// int y = ContainerIntegrationTable.SLOT_Y[i] - 23; -// guiItemStacks.init(i, true, x, y); -// guiItemStacks.set(i, (List) wrapper.getInputs().get(i)); -// } - guiItemStacks.init(inventoryIndex, false, 129, 26); - guiItemStacks.set(inventoryIndex, ingredients.getOutputs(ItemStack.class).get(0)); + guiItemStacks.set(inventoryIndex, ingredients.getOutputs(VanillaTypes.ITEM).get(0)); } } diff --git a/common/buildcraft/compat/module/jei/silicon/HandlerIntegrationTable.java b/common/buildcraft/compat/module/jei/silicon/HandlerIntegrationTable.java deleted file mode 100644 index dfefe11..0000000 --- a/common/buildcraft/compat/module/jei/silicon/HandlerIntegrationTable.java +++ /dev/null @@ -1,38 +0,0 @@ -package buildcraft.compat.module.jei.silicon; - -import buildcraft.api.recipes.IntegrationRecipe; - -import buildcraft.compat.module.jei.BCPluginJEI; - -import mezz.jei.api.recipe.IRecipeWrapper; -import mezz.jei.api.recipe.IRecipeWrapperFactory; - -public class HandlerIntegrationTable implements IRecipeWrapperFactory { - @Override - public IRecipeWrapper getRecipeWrapper(IntegrationRecipe recipe) { - return new WrapperIntegrationTable(BCPluginJEI.registry.getJeiHelpers().getGuiHelper(), recipe); - } - - // -// @Nonnull -// @Override -// public Class getRecipeClass() { -// return IIntegrationRecipe.class; -// } -// -// @Override -// public String getRecipeCategoryUid() { -// return CategoryIntegrationTable.UID; -// } -// -// @Nonnull -// @Override -// public IRecipeWrapper getRecipeWrapper(@Nonnull IIntegrationRecipe recipe) { -// return new WrapperIntegrationTable(BCPluginJEI.registry.getJeiHelpers().getGuiHelper(), recipe); -// } -// -// @Override -// public boolean isRecipeValid(@Nonnull IIntegrationRecipe recipe) { -// return true; -// } -} diff --git a/common/buildcraft/compat/module/jei/silicon/Utils.java b/common/buildcraft/compat/module/jei/silicon/Utils.java index 197c28d..fc026ca 100644 --- a/common/buildcraft/compat/module/jei/silicon/Utils.java +++ b/common/buildcraft/compat/module/jei/silicon/Utils.java @@ -1,15 +1,19 @@ package buildcraft.compat.module.jei.silicon; -import java.util.List; +import buildcraft.api.recipes.StackDefinition; import com.google.common.collect.Lists; import net.minecraft.item.ItemStack; -import buildcraft.api.recipes.StackDefinition; + +import java.util.List; public final class Utils { + public Utils() { + } + public static List getItemStacks(StackDefinition definition) { List list = Lists.newArrayList(); - if (definition.filter != null) { + for (ItemStack stack : definition.filter.getExamples()) { ItemStack sizedStack = stack.copy(); sizedStack.setCount(definition.count); diff --git a/common/buildcraft/compat/module/jei/silicon/WrapperAssemblyTable.java b/common/buildcraft/compat/module/jei/silicon/WrapperAssemblyTable.java deleted file mode 100644 index 0015916..0000000 --- a/common/buildcraft/compat/module/jei/silicon/WrapperAssemblyTable.java +++ /dev/null @@ -1,83 +0,0 @@ -package buildcraft.compat.module.jei.silicon; - -import java.awt.Color; -import java.util.ArrayList; -import java.util.List; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; - -import net.minecraft.client.Minecraft; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; - -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - -import buildcraft.api.mj.MjAPI; -import buildcraft.api.recipes.AssemblyRecipeBasic; -import buildcraft.api.recipes.IngredientStack; - -import buildcraft.compat.module.jei.BCPluginJEI; - -import mezz.jei.api.IGuiHelper; -import mezz.jei.api.gui.IDrawableAnimated; -import mezz.jei.api.gui.IDrawableStatic; -import mezz.jei.api.ingredients.IIngredients; -import mezz.jei.api.recipe.IRecipeWrapper; - -public class WrapperAssemblyTable implements IRecipeWrapper { - private final AssemblyRecipeBasic recipe; - private final IDrawableAnimated progressBar; - private final List> inputs; - private final List outputs; - - public WrapperAssemblyTable(AssemblyRecipeBasic recipe) { - this.recipe = recipe; - List> _inputs = Lists.newArrayList(); - for (IngredientStack in : recipe.getInputsFor(ItemStack.EMPTY)) { - List inner = new ArrayList<>(); - for (ItemStack matching : in.ingredient.getMatchingStacks()) { - matching = matching.copy(); - matching.setCount(in.count); - inner.add(matching); - } - _inputs.add(inner); - } - this.inputs = ImmutableList.copyOf(_inputs); - this.outputs = ImmutableList.copyOf(recipe.getOutputPreviews()); - - IGuiHelper guiHelper = BCPluginJEI.registry.getJeiHelpers().getGuiHelper(); - - ResourceLocation backgroundLocation = - new ResourceLocation("buildcraftsilicon", "textures/gui/assembly_table.png"); - IDrawableStatic progressDrawable = guiHelper.createDrawable(backgroundLocation, 176, 48, 4, 71, 10, 0, 0, 0); - long mj = this.recipe.getRequiredMicroJoulesFor(ItemStack.EMPTY); - progressBar = guiHelper.createAnimatedDrawable(progressDrawable, (int) Math.max(10, mj / MjAPI.MJ / 50), - IDrawableAnimated.StartDirection.BOTTOM, false); - } - - @Override - public void getIngredients(IIngredients ingredients) { - ingredients.setInputLists(ItemStack.class, this.inputs); - ingredients.setOutputs(ItemStack.class, this.outputs); - } - - @Override - @SideOnly(Side.CLIENT) - public void drawInfo(Minecraft minecraft, int recipeWidth, int recipeHeight, int mouseX, int mouseY) { - this.progressBar.draw(minecraft, 81, 2); - long mj = this.recipe.getRequiredMicroJoulesFor(ItemStack.EMPTY); - minecraft.fontRenderer.drawString(MjAPI.formatMj(mj) + " MJ", 4, 0, Color.gray.getRGB()); - } - - @Override - public List getTooltipStrings(int mouseX, int mouseY) { - return Lists.newArrayList(); - } - - @Override - public boolean handleClick(Minecraft minecraft, int mouseX, int mouseY, int mouseButton) { - return false; - } -} diff --git a/common/buildcraft/compat/module/jei/silicon/WrapperIntegrationTable.java b/common/buildcraft/compat/module/jei/silicon/WrapperIntegrationTable.java deleted file mode 100644 index abe1a52..0000000 --- a/common/buildcraft/compat/module/jei/silicon/WrapperIntegrationTable.java +++ /dev/null @@ -1,93 +0,0 @@ -package buildcraft.compat.module.jei.silicon; - -import java.awt.Color; -import java.util.List; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; -import net.minecraft.client.Minecraft; -import net.minecraft.init.Blocks; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; -import buildcraft.api.mj.MjAPI; -import buildcraft.api.recipes.IntegrationRecipe; -import buildcraft.api.recipes.StackDefinition; -import mezz.jei.api.IGuiHelper; -import mezz.jei.api.gui.IDrawableAnimated; -import mezz.jei.api.gui.IDrawableStatic; -import mezz.jei.api.ingredients.IIngredients; -import mezz.jei.api.recipe.IRecipeWrapper; - -public class WrapperIntegrationTable implements IRecipeWrapper { - private final IntegrationRecipe recipe; - private final IDrawableAnimated progressBar; - private final List inputs, outputs; - - public WrapperIntegrationTable(IGuiHelper guiHelper, IntegrationRecipe recipe) { - this.recipe = recipe; - - List inputs = Lists.newArrayList(); -// inputs.addAll(Utils.getItemStacks(recipe.target)); -// for (StackDefinition definition : recipe.toIntegrate) { -// inputs.addAll(Utils.getItemStacks(definition)); -// } - this.inputs = ImmutableList.copyOf(inputs); - this.outputs = ImmutableList.of(new ItemStack(Blocks.COBBLESTONE)); - - ResourceLocation backgroundLocation = new ResourceLocation("buildcraftsilicon", "textures/gui/integration_table.png"); - IDrawableStatic progressDrawable = guiHelper.createDrawable(backgroundLocation, 176, 17, 4, 69, 0, 0, 0, 0); - this.progressBar = guiHelper.createAnimatedDrawable(progressDrawable, (int) (/*recipe.requiredMicroJoules / */ 720), IDrawableAnimated.StartDirection.BOTTOM, false); - } - -// @Override -// public List getInputs() { -// return inputs; -// } -// -// @Override -// public List getOutputs() { -// return outputs; -// } -// -// @Override -// public List getFluidInputs() { -// return null; -// } -// -// @Override -// public List getFluidOutputs() { -// return null; -// } -// -// @Override -// public void drawInfo(Minecraft minecraft, int recipeWidth, int recipeHeight) {} - - @Override - public void getIngredients(IIngredients ingredients) { - ingredients.setInputs(ItemStack.class, this.inputs); - ingredients.setOutputs(ItemStack.class, this.outputs); - } - - @Override - @SideOnly(Side.CLIENT) - public void drawInfo(Minecraft minecraft, int recipeWidth, int recipeHeight, int mouseX, int mouseY) { - this.progressBar.draw(minecraft, 156, 1); - minecraft.fontRenderer.drawString(MjAPI.formatMj(/*this.recipe.requiredMicroJoules*/0) + " MJ", 80, 52, Color.gray.getRGB()); - } -// -// @Override -// public void drawAnimations(Minecraft minecraft, int recipeWidth, int recipeHeight) { -// progressBar.draw(minecraft, 156, 1); -// } - - @Override - public List getTooltipStrings(int mouseX, int mouseY) { - return Lists.newArrayList(); - } - - @Override - public boolean handleClick(Minecraft minecraft, int mouseX, int mouseY, int mouseButton) { - return false; - } -} diff --git a/common/buildcraft/compat/module/jei/silicon/package-info.java b/common/buildcraft/compat/module/jei/silicon/package-info.java index fce7fb1..dceeec5 100644 --- a/common/buildcraft/compat/module/jei/silicon/package-info.java +++ b/common/buildcraft/compat/module/jei/silicon/package-info.java @@ -2,5 +2,6 @@ @MethodsReturnNonnullByDefault package buildcraft.compat.module.jei.silicon; +import mezz.jei.api.MethodsReturnNonnullByDefault; + import javax.annotation.ParametersAreNonnullByDefault; -import mcp.MethodsReturnNonnullByDefault; diff --git a/common/buildcraft/compat/module/jei/transferhandlers/AdvancedCraftingItemsTransferHandler.java b/common/buildcraft/compat/module/jei/transferhandlers/AdvancedCraftingItemsTransferHandler.java index 02282e5..4e6d95e 100644 --- a/common/buildcraft/compat/module/jei/transferhandlers/AdvancedCraftingItemsTransferHandler.java +++ b/common/buildcraft/compat/module/jei/transferhandlers/AdvancedCraftingItemsTransferHandler.java @@ -1,34 +1,32 @@ package buildcraft.compat.module.jei.transferhandlers; -import javax.annotation.Nullable; -import net.minecraft.entity.player.EntityPlayer; import buildcraft.silicon.container.ContainerAdvancedCraftingTable; import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.recipe.transfer.IRecipeTransferError; import mezz.jei.api.recipe.transfer.IRecipeTransferHandler; +import net.minecraft.entity.player.PlayerEntity; + +import javax.annotation.Nullable; public class AdvancedCraftingItemsTransferHandler implements IRecipeTransferHandler { + public AdvancedCraftingItemsTransferHandler() { + } + @Override public Class getContainerClass() { return ContainerAdvancedCraftingTable.class; } - @Nullable @Override - public IRecipeTransferError transferRecipe(ContainerAdvancedCraftingTable container, IRecipeLayout recipeLayout, EntityPlayer player, boolean maxTransfer, boolean doTransfer) { + @Nullable + public IRecipeTransferError transferRecipe(ContainerAdvancedCraftingTable container, IRecipeLayout recipeLayout, PlayerEntity player, boolean maxTransfer, boolean doTransfer) { if (doTransfer) { -// Map> inputs = recipeLayout.getItemStacks().getGuiIngredients(); -// -// for (int slot = 0; slot < 9; slot++) { -// IGuiIngredient ingredient = inputs.getOrDefault(slot + 1, null); -// ItemStack stack = (ingredient == null) ? ItemStack.EMPTY : ingredient.getDisplayedIngredient(); -// -// container.sendSetPhantomSlot(container.tile.invBlueprint, slot, (stack == null) ? ItemStack.EMPTY : stack); -// } - - AutoCraftItemsTransferHandler.transferRecipe( - itemStacks -> container.sendSetPhantomSlots(container.tile.invBlueprint, itemStacks), - recipeLayout); + AutoCraftItemsTransferHandler.transferRecipe((itemStacks) -> + { + container.sendSetPhantomSlots(container.tile.invBlueprint, itemStacks); + }, + recipeLayout + ); } return null; diff --git a/common/buildcraft/compat/module/jei/transferhandlers/AssemblyTableTransferHandler.java b/common/buildcraft/compat/module/jei/transferhandlers/AssemblyTableTransferHandler.java index e0ce8ee..0f72a3a 100644 --- a/common/buildcraft/compat/module/jei/transferhandlers/AssemblyTableTransferHandler.java +++ b/common/buildcraft/compat/module/jei/transferhandlers/AssemblyTableTransferHandler.java @@ -1,23 +1,23 @@ package buildcraft.compat.module.jei.transferhandlers; -import javax.annotation.Nullable; -import net.minecraft.entity.player.EntityPlayer; import buildcraft.silicon.container.ContainerAssemblyTable; import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.recipe.transfer.IRecipeTransferError; import mezz.jei.api.recipe.transfer.IRecipeTransferHandler; +import net.minecraft.entity.player.PlayerEntity; + +import javax.annotation.Nullable; +// Calen: never used in 1.12.2? public class AssemblyTableTransferHandler implements IRecipeTransferHandler { + @Override public Class getContainerClass() { return ContainerAssemblyTable.class; } @Nullable - @Override - public IRecipeTransferError transferRecipe(ContainerAssemblyTable container, IRecipeLayout recipeLayout, EntityPlayer player, boolean maxTransfer, boolean doTransfer) { - - + public IRecipeTransferError transferRecipe(ContainerAssemblyTable container, IRecipeLayout recipeLayout, PlayerEntity player, boolean maxTransfer, boolean doTransfer) { return null; } } diff --git a/common/buildcraft/compat/module/jei/transferhandlers/AutoCraftItemsTransferHandler.java b/common/buildcraft/compat/module/jei/transferhandlers/AutoCraftItemsTransferHandler.java index 5ab756e..4cdb368 100644 --- a/common/buildcraft/compat/module/jei/transferhandlers/AutoCraftItemsTransferHandler.java +++ b/common/buildcraft/compat/module/jei/transferhandlers/AutoCraftItemsTransferHandler.java @@ -1,40 +1,38 @@ package buildcraft.compat.module.jei.transferhandlers; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; -import javax.annotation.Nullable; -import com.google.common.collect.Lists; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.ItemStack; import buildcraft.factory.container.ContainerAutoCraftItems; -import mezz.jei.api.gui.IGuiIngredient; +import com.google.common.collect.Lists; import mezz.jei.api.gui.IRecipeLayout; +import mezz.jei.api.gui.ingredient.IGuiIngredient; import mezz.jei.api.recipe.transfer.IRecipeTransferError; import mezz.jei.api.recipe.transfer.IRecipeTransferHandler; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; public class AutoCraftItemsTransferHandler implements IRecipeTransferHandler { + public AutoCraftItemsTransferHandler() { + } + @Override public Class getContainerClass() { return ContainerAutoCraftItems.class; } - @Nullable @Override - public IRecipeTransferError transferRecipe(ContainerAutoCraftItems container, IRecipeLayout recipeLayout, EntityPlayer player, boolean maxTransfer, boolean doTransfer) { + @Nullable + public IRecipeTransferError transferRecipe(ContainerAutoCraftItems container, IRecipeLayout recipeLayout, PlayerEntity player, boolean maxTransfer, boolean doTransfer) { if (doTransfer) { -// Map> inputs = recipeLayout.getItemStacks().getGuiIngredients(); -// -// for (int slot = 0; slot < 9; slot++) { -// IGuiIngredient ingredient = inputs.getOrDefault(slot + 1, null); -// ItemStack stack = (ingredient == null) ? ItemStack.EMPTY : ingredient.getDisplayedIngredient(); -// -// container.sendSetPhantomSlot(container.tile.invBlueprint, slot, (stack == null) ? ItemStack.EMPTY : stack); -// } - - AutoCraftItemsTransferHandler.transferRecipe( - itemStacks -> container.sendSetPhantomSlots(container.tile.invBlueprint, itemStacks), - recipeLayout); + transferRecipe((itemStacks) -> + { + container.sendSetPhantomSlots((container.tile).invBlueprint, itemStacks); + }, + recipeLayout + ); } return null; diff --git a/common/buildcraft/compat/module/jei/transferhandlers/package-info.java b/common/buildcraft/compat/module/jei/transferhandlers/package-info.java index 546f6b9..06f14f8 100644 --- a/common/buildcraft/compat/module/jei/transferhandlers/package-info.java +++ b/common/buildcraft/compat/module/jei/transferhandlers/package-info.java @@ -2,5 +2,6 @@ @MethodsReturnNonnullByDefault package buildcraft.compat.module.jei.transferhandlers; +import mezz.jei.api.MethodsReturnNonnullByDefault; + import javax.annotation.ParametersAreNonnullByDefault; -import mcp.MethodsReturnNonnullByDefault; diff --git a/common/buildcraft/compat/module/theoneprobe/BCPluginTOP.java b/common/buildcraft/compat/module/theoneprobe/BCPluginTOP.java index 947e923..b526ee6 100644 --- a/common/buildcraft/compat/module/theoneprobe/BCPluginTOP.java +++ b/common/buildcraft/compat/module/theoneprobe/BCPluginTOP.java @@ -1,72 +1,60 @@ package buildcraft.compat.module.theoneprobe; -import static buildcraft.compat.module.theoneprobe.BCPluginTOP.TOP_MOD_ID; - -import java.util.List; - +import buildcraft.api.BCModules; +import buildcraft.api.mj.ILaserTarget; +import buildcraft.api.mj.MjAPI; +import buildcraft.compat.CompatUtils; +import buildcraft.lib.tile.craft.IAssemblyCraft; +import buildcraft.lib.tile.craft.IAutoCraft; import com.google.common.base.Function; - -import net.minecraft.block.state.IBlockState; -import net.minecraft.entity.player.EntityPlayer; +import mcjty.theoneprobe.api.*; +import net.minecraft.block.BlockState; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ResourceLocation; -import net.minecraft.util.text.TextFormatting; +import net.minecraft.util.text.TranslationTextComponent; import net.minecraft.world.World; -import net.minecraftforge.fml.common.Loader; -import net.minecraftforge.fml.common.Optional; -import net.minecraftforge.fml.common.event.FMLInterModComms; - -import buildcraft.api.BCModules; -import buildcraft.api.mj.ILaserTarget; -import buildcraft.api.mj.MjAPI; - -import buildcraft.lib.tile.craft.IAutoCraft; - -import buildcraft.compat.CompatUtils; - -import mcjty.theoneprobe.api.ElementAlignment; -import mcjty.theoneprobe.api.IBlockDisplayOverride; -import mcjty.theoneprobe.api.IProbeHitData; -import mcjty.theoneprobe.api.IProbeInfo; -import mcjty.theoneprobe.api.IProbeInfoProvider; -import mcjty.theoneprobe.api.ITheOneProbe; -import mcjty.theoneprobe.api.ProbeMode; +import java.util.List; -@Optional.InterfaceList({ - @Optional.Interface(modid = TOP_MOD_ID, iface = "mcjty.theoneprobe.api.IBlockDisplayOverride"), - @Optional.Interface(modid = TOP_MOD_ID, iface = "mcjty.theoneprobe.api.IProbeInfoProvider") -}) -public class BCPluginTOP implements Function, IBlockDisplayOverride, IProbeInfoProvider { +//@InterfaceList({@Interface( +// modid = "theoneprobe", +// iface = "mcjty.theoneprobe.api.IBlockDisplayOverride" +//), @Interface( +// modid = "theoneprobe", +// iface = "mcjty.theoneprobe.api.IProbeInfoProvider" +//)}) +//public class BCPluginTOP implements Function, IBlockDisplayOverride, IProbeInfoProvider +public enum BCPluginTOP implements Function, IBlockDisplayOverride, IProbeInfoProvider { + INSTANCE; static final String TOP_MOD_ID = "theoneprobe"; - @Override - @Optional.Method(modid = TOP_MOD_ID) + // @Method(modid = "theoneprobe") public Void apply(ITheOneProbe top) { top.registerBlockDisplayOverride(this); top.registerProvider(this); return null; } - @Override - @Optional.Method(modid = TOP_MOD_ID) - public boolean overrideStandardInfo(ProbeMode mode, IProbeInfo probeInfo, EntityPlayer player, World world, IBlockState blockState, IProbeHitData data) { + // @Method(modid = "theoneprobe") + // public boolean overrideStandardInfo(ProbeMode mode, IProbeInfo probeInfo, EntityPlayer player, World world, IBlockState blockState, IProbeHitData data) + public boolean overrideStandardInfo(ProbeMode mode, IProbeInfo probeInfo, PlayerEntity player, World world, BlockState blockState, IProbeHitData data) { return false; } - @Override - @Optional.Method(modid = TOP_MOD_ID) + // @Method(modid = "theoneprobe") + // public String getID() public String getID() { return "buildcraftcompat.top"; } - @Override - @Optional.Method(modid = TOP_MOD_ID) - public void addProbeInfo(ProbeMode mode, IProbeInfo probeInfo, EntityPlayer player, World world, IBlockState blockState, IProbeHitData data) { + // @Method(modid = "theoneprobe") +// public void addProbeInfo(ProbeMode mode, IProbeInfo probeInfo, EntityPlayer player, World world, IBlockState blockState, IProbeHitData data) + public void addProbeInfo(ProbeMode mode, IProbeInfo probeInfo, PlayerEntity player, World world, BlockState blockState, IProbeHitData data) { ResourceLocation blockRegistryName = blockState.getBlock().getRegistryName(); - if ((blockRegistryName != null) && (BCModules.isBcMod(blockRegistryName.getResourceDomain()))) { - TileEntity entity = world.getTileEntity(data.getPos()); + if (blockRegistryName != null && BCModules.isBcMod(blockRegistryName.getNamespace())) { + TileEntity entity = world.getBlockEntity(data.getPos()); if (entity instanceof IAutoCraft) { this.addAutoCraftInfo(probeInfo, (IAutoCraft) entity); } @@ -74,36 +62,50 @@ public void addProbeInfo(ProbeMode mode, IProbeInfo probeInfo, EntityPlayer play if (entity instanceof ILaserTarget) { this.addLaserTargetInfo(probeInfo, (ILaserTarget) entity); } + + if (entity instanceof IAssemblyCraft) { + this.addAssemblyInfo(probeInfo, (IAssemblyCraft) entity); + } } + } - @Optional.Method(modid = TOP_MOD_ID) + // @Method(modid = "theoneprobe") private void addAutoCraftInfo(IProbeInfo probeInfo, IAutoCraft crafter) { if (!crafter.getCurrentRecipeOutput().isEmpty()) { IProbeInfo mainInfo = probeInfo.vertical(); - mainInfo - .horizontal(mainInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER)) - .text("Making: ") - .item(crafter.getCurrentRecipeOutput()); - IProbeInfo info = mainInfo - .horizontal(mainInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER)) - .text("From: "); +// mainInfo.horizontal(mainInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER)).text("Making: ").item(crafter.getCurrentRecipeOutput()); + mainInfo.horizontal(mainInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER)).text(new TranslationTextComponent("buildcraft.waila.crafting")).item(crafter.getCurrentRecipeOutput()); +// IProbeInfo info = mainInfo.horizontal(mainInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER)).text("From: "); + IProbeInfo info = mainInfo.horizontal(mainInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER)).text(new TranslationTextComponent("buildcraft.waila.crafting_from")); List stacks = CompatUtils.compactInventory(crafter.getInvBlueprint()); - for (ItemStack stack : stacks) + for (ItemStack stack : stacks) { info.item(stack); + } + } else { + IProbeInfo mainInfo = probeInfo.vertical(); + mainInfo.horizontal(mainInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER)).text(new TranslationTextComponent("buildcraft.waila.no_recipe")); } + } - @Optional.Method(modid = TOP_MOD_ID) + // @Method(modid = "theoneprobe") private void addLaserTargetInfo(IProbeInfo probeInfo, ILaserTarget laserTarget) { long power = laserTarget.getRequiredLaserPower(); - if (power > 0) { - probeInfo.horizontal() - .text(TextFormatting.WHITE + "Waiting from laser: ") - .text(TextFormatting.AQUA + MjAPI.formatMj(power)) - .text(TextFormatting.AQUA + "MJ"); + if (power > 0L) { +// probeInfo.horizontal().text(TextFormatting.WHITE + "Waiting from laser: ").text(TextFormatting.AQUA + MjAPI.formatMj(power)).text(TextFormatting.AQUA + "MJ"); + probeInfo.horizontal().text(new TranslationTextComponent("buildcraft.waila.waiting_for_laser", MjAPI.formatMj(power))); } } -} + private void addAssemblyInfo(IProbeInfo probeInfo, IAssemblyCraft assembly) { + ItemStack result = assembly.getAssemblyResult(); + if (!result.isEmpty()) { + probeInfo.horizontal().text(new TranslationTextComponent("buildcraft.waila.crafting")).item(result); + } else { + IProbeInfo mainInfo = probeInfo.vertical(); + mainInfo.horizontal(mainInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER)).text(new TranslationTextComponent("buildcraft.waila.no_recipe")); + } + } +} diff --git a/common/buildcraft/compat/module/theoneprobe/CompatModuleTheOneProbe.java b/common/buildcraft/compat/module/theoneprobe/CompatModuleTheOneProbe.java index 964bc69..a6210ba 100644 --- a/common/buildcraft/compat/module/theoneprobe/CompatModuleTheOneProbe.java +++ b/common/buildcraft/compat/module/theoneprobe/CompatModuleTheOneProbe.java @@ -1,19 +1,18 @@ package buildcraft.compat.module.theoneprobe; -import net.minecraftforge.fml.common.event.FMLInterModComms; - import buildcraft.compat.CompatModuleBase; +import net.minecraftforge.fml.InterModComms; public class CompatModuleTheOneProbe extends CompatModuleBase { + public CompatModuleTheOneProbe() { + } - @Override public String compatModId() { return "theoneprobe"; } - @Override public void preInit() { - FMLInterModComms.sendFunctionMessage(compatModId(), "getTheOneProbe", - "buildcraft.compat.module.theoneprobe.BCPluginTOP"); +// FMLInterModComms.sendFunctionMessage(this.compatModId(), "getTheOneProbe", "buildcraft.compat.module.theoneprobe.BCPluginTOP"); + InterModComms.sendTo(this.compatModId(), "getTheOneProbe", () -> BCPluginTOP.INSTANCE); } } diff --git a/common/buildcraft/compat/module/waila/AssemblyCraftDataProvider.java b/common/buildcraft/compat/module/waila/AssemblyCraftDataProvider.java new file mode 100644 index 0000000..f02af54 --- /dev/null +++ b/common/buildcraft/compat/module/waila/AssemblyCraftDataProvider.java @@ -0,0 +1,51 @@ +package buildcraft.compat.module.waila; + +import buildcraft.lib.tile.craft.IAssemblyCraft; +import mcp.mobius.waila.api.IDataAccessor; +import mcp.mobius.waila.api.IPluginConfig; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.StringTextComponent; +import net.minecraft.util.text.TranslationTextComponent; +import net.minecraft.world.World; +import net.minecraftforge.common.util.Constants; + +import java.util.List; + +public class AssemblyCraftDataProvider { + static class BodyProvider extends BaseWailaDataProvider.BodyProvider { + @Override + public void getWailaBody(List currentTip, IDataAccessor accessor, IPluginConfig iPluginConfig) { + TileEntity tile = accessor.getTileEntity(); + if (tile instanceof IAssemblyCraft) { +// CompoundTag nbt = accessor.getNBTData(); + CompoundNBT nbt = accessor.getServerData(); + if (nbt.contains("recipe_result", Constants.NBT.TAG_COMPOUND)) { + ItemStack recipe_result = ItemStack.of(nbt.getCompound("recipe_result")); + if (!recipe_result.isEmpty()) { + currentTip.add(new TranslationTextComponent("buildcraft.waila.crafting")); + currentTip.add(HWYLAPlugin.getItemStackString(recipe_result)); + return; + } + } + currentTip.add(new TranslationTextComponent("buildcraft.waila.no_recipe")); + } +// else { +// currentTip.add(new TextComponent(ChatFormatting.RED + "{wrong tile entity}")); +// } + } + } + + static class NBTProvider extends BaseWailaDataProvider.NBTProvider { + @Override + public void getNBTData(CompoundNBT nbt, ServerPlayerEntity player, World world, TileEntity tile) { + if (tile instanceof IAssemblyCraft) { + IAssemblyCraft assembly = (IAssemblyCraft) tile; + nbt.put("recipe_result", assembly.getAssemblyResult().serializeNBT()); + } + } + } +} diff --git a/common/buildcraft/compat/module/waila/AutoCraftDataProvider.java b/common/buildcraft/compat/module/waila/AutoCraftDataProvider.java index df1f7c4..6a6dd20 100644 --- a/common/buildcraft/compat/module/waila/AutoCraftDataProvider.java +++ b/common/buildcraft/compat/module/waila/AutoCraftDataProvider.java @@ -1,83 +1,75 @@ package buildcraft.compat.module.waila; -import static buildcraft.compat.module.waila.HWYLAPlugin.WAILA_MOD_ID; - -import java.util.List; - -import javax.annotation.Nonnull; - -import net.minecraft.entity.player.EntityPlayerMP; +import buildcraft.compat.CompatUtils; +import buildcraft.lib.tile.craft.IAutoCraft; +import mcp.mobius.waila.api.IDataAccessor; +import mcp.mobius.waila.api.IPluginConfig; +import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.ListNBT; import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.text.TextFormatting; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.StringTextComponent; +import net.minecraft.util.text.TranslationTextComponent; import net.minecraft.world.World; - import net.minecraftforge.common.util.Constants; -import net.minecraftforge.fml.common.Optional; -import buildcraft.lib.tile.craft.IAutoCraft; - -import buildcraft.compat.CompatUtils; +import java.util.List; -import mcp.mobius.waila.api.IWailaConfigHandler; -import mcp.mobius.waila.api.IWailaDataAccessor; -import mcp.mobius.waila.api.SpecialChars; +public class AutoCraftDataProvider { -class AutoCraftDataProvider extends BaseWailaDataProvider { - @Nonnull - @Override - @Optional.Method(modid = WAILA_MOD_ID) - public List getWailaBody(ItemStack itemStack, List currentTip, IWailaDataAccessor accessor, IWailaConfigHandler config) { - TileEntity tile = accessor.getTileEntity(); - if (tile instanceof IAutoCraft) { - NBTTagCompound nbt = accessor.getNBTData(); - if (nbt.hasKey("recipe_result", Constants.NBT.TAG_COMPOUND)) { - ItemStack result = new ItemStack(nbt.getCompoundTag("recipe_result")); - currentTip.add(TextFormatting.WHITE + "Making: " + SpecialChars.WailaSplitter + HWYLAPlugin.getItemStackString(result)); + static class BodyProvider extends BaseWailaDataProvider.BodyProvider { + @Override + public void getWailaBody(List currentTip, IDataAccessor accessor, IPluginConfig config) { + TileEntity tile = accessor.getTileEntity(); + if (tile instanceof IAutoCraft) { + CompoundNBT nbt = accessor.getServerData(); + if (nbt.contains("recipe_result", Constants.NBT.TAG_COMPOUND)) { + // Calen: add -> create new line / append -> append at the last line + ItemStack result = ItemStack.of(nbt.getCompound("recipe_result")); + currentTip.add(new TranslationTextComponent("buildcraft.waila.crafting")); + currentTip.add(HWYLAPlugin.getItemStackString(result)); + // Calen: an empty line, because the item icon is 2 lines height + // if ItemStackElement.of(result, 0.5F), the count text of the stack will not scale + currentTip.add(new StringTextComponent("")); + if (nbt.contains("recipe_inputs", Constants.NBT.TAG_LIST)) { + ListNBT list = nbt.getList("recipe_inputs", Constants.NBT.TAG_COMPOUND); + currentTip.add(new TranslationTextComponent("buildcraft.waila.crafting_from")); - if (nbt.hasKey("recipe_inputs", Constants.NBT.TAG_LIST)) { - NBTTagList list = nbt.getTagList("recipe_inputs", Constants.NBT.TAG_COMPOUND); - StringBuilder inputs = new StringBuilder(TextFormatting.WHITE + "From: " + SpecialChars.WailaSplitter); - for (int index = 0; index < list.tagCount(); index++) { - NBTTagCompound compound = NBTTagCompound.class.cast(list.get(index)); - inputs.append(HWYLAPlugin.getItemStackString(new ItemStack(compound))); + for (int index = 0; index < list.size(); ++index) { + CompoundNBT compound = list.getCompound(index); + currentTip.add(HWYLAPlugin.getItemStackString(ItemStack.of(compound))); + } } - currentTip.add(inputs.toString()); + } else { + currentTip.add(new TranslationTextComponent("buildcraft.waila.no_recipe")); } - } else { - currentTip.add(TextFormatting.GRAY + "No recipe"); } - } else { - currentTip.add(TextFormatting.RED + "{wrong tile entity}"); +// else { +// currentTip.add(new TextComponent(ChatFormatting.RED + "{wrong tile entity}")); +// } } - return currentTip; } - @Nonnull - @Override - @Optional.Method(modid = WAILA_MOD_ID) - public NBTTagCompound getNBTData(EntityPlayerMP player, TileEntity te, NBTTagCompound tag, World world, BlockPos pos) { - NBTTagCompound nbt = super.getNBTData(player, te, tag, world, pos); + static class NBTProvider extends BaseWailaDataProvider.NBTProvider { + @Override + public void getNBTData(CompoundNBT nbt, ServerPlayerEntity player, World world, TileEntity tile) { + if (tile instanceof IAutoCraft) { + IAutoCraft auto = (IAutoCraft) tile; + ItemStack output = auto.getCurrentRecipeOutput(); + if (!output.isEmpty()) { + nbt.put("recipe_result", output.serializeNBT()); + List stacks = CompatUtils.compactInventory(auto.getInvBlueprint()); + ListNBT list = new ListNBT(); - TileEntity tile = world.getTileEntity(pos); - if (tile instanceof IAutoCraft) { - IAutoCraft auto = IAutoCraft.class.cast(tile); - ItemStack output = auto.getCurrentRecipeOutput(); - if (!output.isEmpty()) { - nbt.setTag("recipe_result", output.serializeNBT()); + for (int index = 0; index < stacks.size(); ++index) { + list.add((stacks.get(index)).serializeNBT()); + } - List stacks = CompatUtils.compactInventory(auto.getInvBlueprint()); - NBTTagList list = new NBTTagList(); - for (int index = 0; index < stacks.size(); index++) { - list.appendTag(stacks.get(index).serializeNBT()); + nbt.put("recipe_inputs", list); } - nbt.setTag("recipe_inputs", list); } } - - return nbt; } } diff --git a/common/buildcraft/compat/module/waila/BaseWailaDataProvider.java b/common/buildcraft/compat/module/waila/BaseWailaDataProvider.java index 630b8af..679b20f 100644 --- a/common/buildcraft/compat/module/waila/BaseWailaDataProvider.java +++ b/common/buildcraft/compat/module/waila/BaseWailaDataProvider.java @@ -1,57 +1,35 @@ package buildcraft.compat.module.waila; -import static buildcraft.compat.module.waila.HWYLAPlugin.WAILA_MOD_ID; - -import java.util.List; -import javax.annotation.Nonnull; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; +import mcp.mobius.waila.api.IComponentProvider; +import mcp.mobius.waila.api.IDataAccessor; +import mcp.mobius.waila.api.IPluginConfig; +import mcp.mobius.waila.api.IServerDataProvider; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.nbt.CompoundNBT; import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.ITextComponent; import net.minecraft.world.World; -import net.minecraftforge.fml.common.Optional; -import mcp.mobius.waila.api.IWailaConfigHandler; -import mcp.mobius.waila.api.IWailaDataAccessor; -import mcp.mobius.waila.api.IWailaDataProvider; +import java.util.List; -@Optional.InterfaceList({ - @Optional.Interface(modid = WAILA_MOD_ID, iface = "mcp.mobius.waila.api.IWailaDataProvider") -}) -class BaseWailaDataProvider implements IWailaDataProvider { - @Nonnull - @Override - @Optional.Method(modid = WAILA_MOD_ID) - public ItemStack getWailaStack(IWailaDataAccessor accessor, IWailaConfigHandler config) { - return ItemStack.EMPTY; - } +//class BaseWailaDataProvider implements IWailaDataProvider +public interface BaseWailaDataProvider { - @Nonnull - @Override - @Optional.Method(modid = WAILA_MOD_ID) - public List getWailaHead(ItemStack itemStack, List currentTip, IWailaDataAccessor accessor, IWailaConfigHandler config) { - return currentTip; - } + static abstract class BodyProvider implements IComponentProvider { + @Override + public void appendBody(List currentTip, IDataAccessor accessor, IPluginConfig iPluginConfig) { + getWailaBody(currentTip, accessor, iPluginConfig); + } - @Nonnull - @Override - @Optional.Method(modid = WAILA_MOD_ID) - public List getWailaBody(ItemStack itemStack, List currentTip, IWailaDataAccessor accessor, IWailaConfigHandler config) { - return currentTip; + abstract void getWailaBody(List currentTip, IDataAccessor accessor, IPluginConfig iPluginConfig); } - @Nonnull - @Override - @Optional.Method(modid = WAILA_MOD_ID) - public List getWailaTail(ItemStack itemStack, List currentTip, IWailaDataAccessor accessor, IWailaConfigHandler config) { - return currentTip; - } + static abstract class NBTProvider implements IServerDataProvider { + @Override + public void appendServerData(CompoundNBT nbt, ServerPlayerEntity player, World world, TileEntity tile) { + getNBTData(nbt, player, world, tile); + } - @Nonnull - @Override - @Optional.Method(modid = WAILA_MOD_ID) - public NBTTagCompound getNBTData(EntityPlayerMP player, TileEntity te, NBTTagCompound tag, World world, BlockPos pos) { - return tag; + abstract void getNBTData(CompoundNBT nbt, ServerPlayerEntity player, World world, TileEntity tile); } } diff --git a/common/buildcraft/compat/module/waila/HWYLAPlugin.java b/common/buildcraft/compat/module/waila/HWYLAPlugin.java index 2ddff63..1dbdbce 100644 --- a/common/buildcraft/compat/module/waila/HWYLAPlugin.java +++ b/common/buildcraft/compat/module/waila/HWYLAPlugin.java @@ -1,49 +1,48 @@ package buildcraft.compat.module.waila; -import static buildcraft.compat.module.waila.HWYLAPlugin.WAILA_MOD_ID; - +import buildcraft.lib.block.BlockBCTile_Neptune; +import buildcraft.lib.tile.TileBC_Neptune; +import mcp.mobius.waila.api.*; import net.minecraft.item.ItemStack; - -import net.minecraftforge.fml.common.Optional; - -import buildcraft.api.mj.ILaserTarget; - -import buildcraft.lib.tile.craft.IAutoCraft; - -import mcp.mobius.waila.api.IWailaDataProvider; -import mcp.mobius.waila.api.IWailaPlugin; -import mcp.mobius.waila.api.IWailaRegistrar; -import mcp.mobius.waila.api.SpecialChars; -import mcp.mobius.waila.api.WailaPlugin; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.StringTextComponent; @WailaPlugin -@Optional.InterfaceList({ - @Optional.Interface(modid = WAILA_MOD_ID, iface = "mcp.mobius.waila.api.IWailaPlugin") -}) public class HWYLAPlugin implements IWailaPlugin { - static final String WAILA_MOD_ID = "waila"; + // Calen: in 1.18.2 we should use Block or TE class instead of interface here, it's too difficult to get all matched if allowing some BC modules absent, + // so just use TileBC_Neptune and BlockBCTile_Neptune @Override - public void register(IWailaRegistrar registrar) { - IWailaDataProvider autoCraftProvider = new AutoCraftDataProvider(); - registrar.registerNBTProvider(autoCraftProvider, IAutoCraft.class); - registrar.registerBodyProvider(autoCraftProvider, IAutoCraft.class); - - IWailaDataProvider laserTargetProvider = new LaserTargetDataProvider(); - registrar.registerNBTProvider(laserTargetProvider, ILaserTarget.class); - registrar.registerBodyProvider(laserTargetProvider, ILaserTarget.class); + public void register(IRegistrar registrar) { + IServerDataProvider autoCraftNbtProvider = new AutoCraftDataProvider.NBTProvider(); + IServerDataProvider laserTargetNbtProvider = new LaserTargetDataProvider.NBTProvider(); + IServerDataProvider assemblyCraftNbtProvider = new AssemblyCraftDataProvider.NBTProvider(); + + registrar.registerBlockDataProvider(autoCraftNbtProvider, TileBC_Neptune.class); + registrar.registerBlockDataProvider(laserTargetNbtProvider, TileBC_Neptune.class); + registrar.registerBlockDataProvider(assemblyCraftNbtProvider, TileBC_Neptune.class); + + IComponentProvider autoCraftBodyProvider = new AutoCraftDataProvider.BodyProvider(); + IComponentProvider laserTargetBodyProvider = new LaserTargetDataProvider.BodyProvider(); + IComponentProvider assemblyCraftBodyProvider = new AssemblyCraftDataProvider.BodyProvider(); + + registrar.registerComponentProvider(autoCraftBodyProvider, TooltipPosition.BODY, BlockBCTile_Neptune.class); + registrar.registerComponentProvider(laserTargetBodyProvider, TooltipPosition.BODY, BlockBCTile_Neptune.class); + registrar.registerComponentProvider(assemblyCraftBodyProvider, TooltipPosition.BODY, BlockBCTile_Neptune.class); } - static String getItemStackString(ItemStack stack) { + static ITextComponent getItemStackString(ItemStack stack) { return getItemStackString(stack, "1"); } - private static String getItemStackString(ItemStack stack, String thing) { + private static ITextComponent getItemStackString(ItemStack stack, String thing) { // TODO: find out what that 'thing' really is - return SpecialChars.getRenderString("waila.stack", thing, - stack.getItem().getRegistryName().toString(), - String.valueOf(stack.getCount()), - String.valueOf(stack.getItemDamage()) - ); +// return SpecialChars.getRenderString("waila.stack", thing, +// stack.getItem().getRegistryName().toString(), +// String.valueOf(stack.getCount()), +// String.valueOf(stack.getDamageValue()) +// ); + return new StringTextComponent("").append(stack.getDisplayName()).append(" x " + stack.getCount()); } } diff --git a/common/buildcraft/compat/module/waila/LaserTargetDataProvider.java b/common/buildcraft/compat/module/waila/LaserTargetDataProvider.java index 426e975..3cc5b45 100644 --- a/common/buildcraft/compat/module/waila/LaserTargetDataProvider.java +++ b/common/buildcraft/compat/module/waila/LaserTargetDataProvider.java @@ -1,56 +1,46 @@ package buildcraft.compat.module.waila; -import static buildcraft.compat.module.waila.HWYLAPlugin.WAILA_MOD_ID; - -import java.util.List; -import javax.annotation.Nonnull; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; +import buildcraft.api.mj.ILaserTarget; +import buildcraft.api.mj.MjAPI; +import mcp.mobius.waila.api.IDataAccessor; +import mcp.mobius.waila.api.IPluginConfig; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.nbt.CompoundNBT; import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.text.TextFormatting; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TranslationTextComponent; import net.minecraft.world.World; import net.minecraftforge.common.util.Constants; -import net.minecraftforge.fml.common.Optional; -import buildcraft.api.mj.ILaserTarget; -import buildcraft.api.mj.MjAPI; -import mcp.mobius.waila.api.IWailaConfigHandler; -import mcp.mobius.waila.api.IWailaDataAccessor; +import java.util.List; -class LaserTargetDataProvider extends BaseWailaDataProvider { - @Nonnull - @Override - @Optional.Method(modid = WAILA_MOD_ID) - public List getWailaBody(ItemStack itemStack, List currentTip, IWailaDataAccessor accessor, IWailaConfigHandler config) { - TileEntity tile = accessor.getTileEntity(); - if (tile instanceof ILaserTarget) { - NBTTagCompound nbt = accessor.getNBTData(); - if (nbt.hasKey("required_power", Constants.NBT.TAG_LONG)) { - long power = nbt.getLong("required_power"); - if (power > 0) { - currentTip.add(TextFormatting.WHITE + "Waiting from laser: " + TextFormatting.AQUA + MjAPI.formatMj(power) + " MJ"); +class LaserTargetDataProvider { + static class BodyProvider extends BaseWailaDataProvider.BodyProvider { + @Override + public void getWailaBody(List currentTip, IDataAccessor accessor, IPluginConfig iPluginConfig) { + TileEntity tile = accessor.getTileEntity(); + if (tile instanceof ILaserTarget) { + CompoundNBT nbt = accessor.getServerData(); + if (nbt.contains("required_power", Constants.NBT.TAG_LONG)) { + long power = nbt.getLong("required_power"); + if (power > 0L) { + currentTip.add(new TranslationTextComponent("buildcraft.waila.waiting_for_laser", MjAPI.formatMj(power))); + } } } - } else { - currentTip.add(TextFormatting.RED + "{wrong tile entity}"); +// else { +// currentTip.add(new TextComponent(ChatFormatting.RED + "{wrong tile entity}")); +// } } - return currentTip; } - @Nonnull - @Override - @Optional.Method(modid = WAILA_MOD_ID) - public NBTTagCompound getNBTData(EntityPlayerMP player, TileEntity te, NBTTagCompound tag, World world, BlockPos pos) { - NBTTagCompound nbt = super.getNBTData(player, te, tag, world, pos); - - TileEntity tile = world.getTileEntity(pos); - if (tile instanceof ILaserTarget) { - ILaserTarget target = ILaserTarget.class.cast(tile); - nbt.setLong("required_power", target.getRequiredLaserPower()); + static class NBTProvider extends BaseWailaDataProvider.NBTProvider { + @Override + public void getNBTData(CompoundNBT nbt, ServerPlayerEntity player, World world, TileEntity tile) { + if (tile instanceof ILaserTarget) { + ILaserTarget target = (ILaserTarget) tile; + nbt.putLong("required_power", target.getRequiredLaserPower()); + } } - - return nbt; } } diff --git a/common/buildcraft/compat/network/CompatGui.java b/common/buildcraft/compat/network/CompatGui.java index 3c5d599..75212fc 100644 --- a/common/buildcraft/compat/network/CompatGui.java +++ b/common/buildcraft/compat/network/CompatGui.java @@ -1,144 +1,160 @@ -package buildcraft.compat.network; - -import javax.annotation.Nullable; - -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -import net.minecraftforge.fml.common.SidedProxy; -import net.minecraftforge.fml.common.network.IGuiHandler; - -import buildcraft.compat.BCCompat; -import buildcraft.compat.CompatUtils; - -// Half-decent class (inspired by how forestry does things) -// This really wants fleshing out and moving into mainline buildcraft though -// Along with a sensible way of dealing with pluggables etc -public enum CompatGui { - - FORESTRY_PROPOLIS_PIPE(IGuiTarget.TILE); - - static final CompatGui[] VALUES = values(); - - @SidedProxy(modId = BCCompat.MODID) - public static CommonProxy guiHandlerProxy; - - public final IGuiTarget target; - - private CompatGui(IGuiTarget target) { - this.target = target; - } - - public void openGui(EntityPlayer player) { - openGui(player, 0, 0, 0, 0); - } - - public void openGui(EntityPlayer player, BlockPos pos) { - openGui(player, pos.getX(), pos.getY(), pos.getZ(), 0); - } - - public void openGui(EntityPlayer player, int x, int y, int z) { - openGui(player, x, y, z, 0); - } - - public void openGui(EntityPlayer player, int data) { - openGui(player, 0, 0, 0, data); - } - - public void openGui(EntityPlayer player, BlockPos pos, int data) { - openGui(player, pos.getX(), pos.getY(), pos.getZ(), data); - } - - public void openGui(EntityPlayer player, int x, int y, int z, int data) { - player.openGui(BCCompat.instance, packGui(this, data), player.world, x, y, z); - } - - protected static int packGui(Enum gui, int data) { - if (data < 0 || data > 0xFF_FF_FF) { - throw new IllegalArgumentException("Data must be between 0 and 0xFF_FF_FF (inclusive)"); - } - return (data << 8) | gui.ordinal(); - } - - @Nullable - protected static CompatGui getGui(int id) { - id &= 0xFF; - if (id < 0 || id >= CompatGui.VALUES.length) { - return null; - } - return CompatGui.VALUES[id]; - } - - protected static int getData(int id) { - return id >>> 8; - } - - @FunctionalInterface - public interface IGuiTarget { - public static final IGuiTarget TILE = (player, world, x, y, z, data) -> { - TileEntity tile = world.getTileEntity(new BlockPos(x, y, z)); - if (tile instanceof IGuiCreator) { - return (IGuiCreator) tile; - } - if (tile != null) { - return tile.getCapability(CompatUtils.CAP_GUI_CREATOR, null); - } - return null; - }; - - @Nullable - IGuiCreator getCreator(EntityPlayer player, World world, int x, int y, int z, int data); - } - - public static abstract class CommonProxy implements IGuiHandler { - - @Nullable - protected static IGuiCreator getGuiCreator(int id, EntityPlayer player, World world, int x, int y, int z) { - CompatGui type = getGui(id); - int data = getData(id); - if (type == null) { - return null; - } - IGuiCreator creator = type.target.getCreator(player, world, x, y, z, data); - if (creator == null || creator.getGuiType() != type) { - return null; - } - return creator; - } - - @Override - @Nullable - public Object getServerGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) { - IGuiCreator creator = getGuiCreator(id, player, world, x, y, z); - if (creator == null) { - return null; - } - return creator.getServerGuiElement(getData(id), player); - } - } - - public static class ServerProxy extends CommonProxy { - - @Override - @Nullable - public Object getClientGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) { - return null; - } - } - - public static class ClientProxy extends CommonProxy { - - @Override - @Nullable - public Object getClientGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) { - IGuiCreator creator = getGuiCreator(id, player, world, x, y, z); - if (creator == null) { - return null; - } - return creator.getClientGuiElement(getData(id), player); - } - } - -} +//package buildcraft.compat.network; +// +//import buildcraft.compat.BCCompat; +//import buildcraft.compat.CompatUtils; +//import net.minecraft.core.BlockPos; +//import net.minecraft.core.Direction; +//import net.minecraft.world.entity.player.Player; +//import net.minecraft.world.level.Level; +//import net.minecraft.world.level.block.entity.BlockEntity; +// +//import javax.annotation.Nullable; +// +//public enum CompatGui +//{ +// FORESTRY_PROPOLIS_PIPE(CompatGui.IGuiTarget.TILE); +// +// static final CompatGui[] VALUES = values(); +// // @SidedProxy( +//// modId = "buildcraftcompat" +//// ) +// public static CommonProxy guiHandlerProxy; +// public final IGuiTarget target; +// +// private CompatGui(IGuiTarget target) +// { +// this.target = target; +// } +// +// public void openGui(EntityPlayer player) +// { +// this.openGui(player, 0, 0, 0, 0); +// } +// +// public void openGui(EntityPlayer player, BlockPos pos) +// { +// this.openGui(player, pos.func_177958_n(), pos.func_177956_o(), pos.func_177952_p(), 0); +// } +// +// public void openGui(EntityPlayer player, int x, int y, int z) +// { +// this.openGui(player, x, y, z, 0); +// } +// +// public void openGui(EntityPlayer player, int data) +// { +// this.openGui(player, 0, 0, 0, data); +// } +// +// public void openGui(EntityPlayer player, BlockPos pos, int data) +// { +// this.openGui(player, pos.func_177958_n(), pos.func_177956_o(), pos.func_177952_p(), data); +// } +// +// public void openGui(EntityPlayer player, int x, int y, int z, int data) +// { +// player.openGui(BCCompat.instance, packGui(this, data), player.field_70170_p, x, y, z); +// } +// +// protected static int packGui(Enum gui, int data) +// { +// if (data >= 0 && data <= 16777215) +// { +// return data << 8 | gui.ordinal(); +// } +// else +// { +// throw new IllegalArgumentException("Data must be between 0 and 0xFF_FF_FF (inclusive)"); +// } +// } +// +// @Nullable +// protected static CompatGui getGui(int id) +// { +// id &= 255; +// return id >= 0 && id < VALUES.length ? VALUES[id] : null; +// } +// +// protected static int getData(int id) +// { +// return id >>> 8; +// } +// +// public static class ClientProxy extends CommonProxy +// { +// public ClientProxy() +// { +// } +// +// @Nullable +// public Object getClientGuiElement(int id, Player player, Level world, int x, int y, int z) +// { +// IGuiCreator creator = getGuiCreator(id, player, world, x, y, z); +// return creator == null ? null : creator.getClientGuiElement(CompatGui.getData(id), player); +// } +// } +// +// public static class ServerProxy extends CommonProxy +// { +// public ServerProxy() +// { +// } +// +// @Nullable +// public Object getClientGuiElement(int id, Player player, Level world, int x, int y, int z) +// { +// return null; +// } +// } +// +// // public abstract static class CommonProxy implements IGuiHandler +// public abstract static class CommonProxy +// { +// public CommonProxy() +// { +// } +// +// @Nullable +// protected static IGuiCreator getGuiCreator(int id, Player player, Level world, int x, int y, int z) +// { +// CompatGui type = CompatGui.getGui(id); +// int data = CompatGui.getData(id); +// if (type == null) +// { +// return null; +// } +// else +// { +// IGuiCreator creator = type.target.getCreator(player, world, x, y, z, data); +// return creator != null && creator.getGuiType() == type ? creator : null; +// } +// } +// +// @Nullable +// public Object getServerGuiElement(int id, Player player, Level world, int x, int y, int z) +// { +// IGuiCreator creator = getGuiCreator(id, player, world, x, y, z); +// return creator == null ? null : creator.getServerGuiElement(CompatGui.getData(id), player); +// } +// } +// +// @FunctionalInterface +// public interface IGuiTarget +// { +// IGuiTarget TILE = (player, world, x, y, z, data) -> +// { +// BlockEntity tile = world.getBlockEntity(new BlockPos(x, y, z)); +// if (tile instanceof IGuiCreator) +// { +// return (IGuiCreator) tile; +// } +// else +// { +// return tile != null ? (IGuiCreator) tile.getCapability(CompatUtils.CAP_GUI_CREATOR, null) : null; +// } +// }; +// +// @Nullable +// IGuiCreator getCreator(Player var1, Level var2, int var3, int var4, int var5, int var6); +// } +//} diff --git a/common/buildcraft/compat/network/IGuiCreator.java b/common/buildcraft/compat/network/IGuiCreator.java index c1d26fe..fc7c976 100644 --- a/common/buildcraft/compat/network/IGuiCreator.java +++ b/common/buildcraft/compat/network/IGuiCreator.java @@ -1,25 +1,21 @@ package buildcraft.compat.network; -import javax.annotation.Nullable; - -import net.minecraft.client.gui.inventory.GuiContainer; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.inventory.Container; +import net.minecraft.client.gui.screen.inventory.ContainerScreen; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; +import javax.annotation.Nullable; -/** A creator that can */ -// TODO: Move this into bc lib and make it more useful! public interface IGuiCreator { Enum getGuiType(); - /** @param data The extra 24 bits that are unused by the byte ID. */ @Nullable - @SideOnly(Side.CLIENT) - GuiContainer getClientGuiElement(int data, EntityPlayer player); + @OnlyIn(Dist.CLIENT) +// GuiContainer getClientGuiElement(int var1, EntityPlayer var2); + ContainerScreen getClientGuiElement(int var1, PlayerEntity var2); - /** @param data The extra 24 bits that are unused by the byte ID. */ @Nullable - Container getServerGuiElement(int data, EntityPlayer player); +// Container getServerGuiElement(int var1, EntityPlayer var2); + ContainerScreen getServerGuiElement(int var1, PlayerEntity var2); } diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..878bf1f --- /dev/null +++ b/gradle.properties @@ -0,0 +1,4 @@ +# Sets default memory used for gradle commands. Can be overridden by user or command line properties. +# This is required to provide enough memory for the Minecraft decompilation process. +org.gradle.jvmargs=-Xmx3G +org.gradle.daemon=false \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index ca78035ef0501d802d4fc55381ef2d5c3ce0ec6e..e708b1c023ec8b20f512888fe07c5bd3ff77bb8f 100644 GIT binary patch literal 59203 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

K7UpUK$>l@ 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 E2O(~oYXATM literal 53556 zcmafaW3XsJ(%7|a+qP}nwr$(CZQFj=wr$(@UA(+xH(#=wO)^z|&iv@9neOWDX^nz3 zFbEU?00abpJ7cBo`loO)|22l7HMDRNfRDr(;s(%6He@B!R zl#>(_RaT*s6?>AMo|2KKrCWfNrlp#lo@-WOSZ3Zod7P#lmzMGa(ZwA{NHx8{)|HLtOGBmL<{ePk& z|0}Aylc9rysnh?l#3IPVtoSeL%3mP<&r3w?-R*4b4NXWG>5Od*ot=GSWT6Hb5JLAX zShc9#=!2lw!t#FMI}pFJc zw6Uj8`Bst|cD2?nsG(d*ZG#%NF?Y80v0PGQSJPsUg@n3BQIkW_dR~d>N{{*bSH}Pd zIWdTJ#iH#>%S&)$tqoH6b*V7fLp<>(xL_ji`jq2`%oD)~iD7`@hsO@Vy3*qM{u`G^ zc0*TD{z`zuUlxn}e`r+pbapYdRdBNZ%Pbd5Q|G@k4^Kf?7YkE67fWM97kj6FFrif0 z)*eX^!4Hihd~D&c(x5hVbJa`bB+7ol01GlU5|UB2N>+y7))3gd&fUa5@v;6n+Lq-3 z{Jl7)Ss;}F5czIs_L}Eunuojl?dWXn4q(#5iYPV+5*ifPnsS@1F)kK`O<80078hB& z!Uu$#cM=e$$6FUI2Uys(|$Fxqmy zG@_F97OGMH;TUgxma36@BQi`!B{e(ZeayiDo z;os4R9{50YQVC-ThdC9S{Ee)4ikHa8|X*ach%>dfECip|EPi!8S zDh{J&bjYD?EYtrlYx3Xq_Uu~2x$3X9ZT$tJ|15Qq|5LU8AycBUzy2x~OxU04i>D z9w@yRqlcbqC}2T_XT5eNHYx5)7rtz8{DE*J?o>>OiS)0JC!ZaB0JL-Ob1w)8zanZ< zR(Xiz3$ioy*%XQmL-bJnNfvE$rI2P~LX90G#gt4nb9mku*6S{mqFw`_kt{LAkj!x21fSFo(-^4px?_hH9-@XW8zqNrs(RYSX5R zn7kQuX>YGYLyM(G>^wtn&><_Q!~W27r537fQwZIqYL965<@&T|=xUF6c$g=5 z9B|kBeu>}r8R@-o3b!=}4_HG6sot1tgjjbmglPS~q)5GX6CU&gxsD0v9llaw7Bh7W zG`o>aya0{@c}L+Gw`1PRqcl6e6}@o3Bcd#mP)9H<2a|Wi{ZWqCzX%93IfRpvQ5Gba z7lEPC4fM4WC?*W3IpV-cRPh5Sc}Q>vS@2qu<+V(nS%!Sm&*^W!gSj)# z5h9&o{KIKp2kov&g`CP%-CqAqA#o0Mw?;q#0Dk{<4VeG4n2LHB+qgPgx|xbu+L#I& z8=E>i%Np7lnw$R9>ZhtnJ0P3l{ISg3VawG!KBZ_pvN2DYtK&W!-f06 z`*U{p=QkVw&*us(0Q^xhL0e%n5Ms&j;)%FBf*#J>kq82xOVpI4<0WK)`n9DXCuv$A zfn4!kd?3Iqh$3+WD+l&4vj>}m@*Jom+}vj&2m=KQGoVRm7M2KY7**ns0|M5px)Deh zez6~hUk1`@NgO%XoGXd)&6$_Hs|(2|X^7HUDkEtbwHV#1wRTpbb)rHlLu^njhFg9S zx+)}U8(USDXm>S%pp;a_Y<5>3i_Hp_vWwtzt5uj8ewqTFEE)E15)Wjvv?x}}8HMiX z;^3-OH85AzcV_0O-Exhrj`RpUZ;j$qjmZ|L#+*_US5`JV%8wqakxhD&XCpyuWo{N- z+bNS}p+afKlpHI>3VBBeq|G8boGeUaC)(Ru3u`YLW30>~)5=GL=sUjLgu65%VcPGs}PA z2_OLv=2)9Xm11f*FTt*o*yc8FG>4G~q{mOUX#}$!=u>KSGyX(=*}&rI;2K(U?Koxp z7F-pc*}}pO@m;7sff=FGTE4TA9ZNTRx%XWeaa|lx9o$qjHByj0HxuO5TvpM}CwTW> z#R=1vZp)76kO?#z;(>6Mu&gCwrlvRCVG_g8sMl;^DrH)&-*)v5ZHl3IWWpPi!|ZNQ z4&vdL!lWNaYH)lo!KJkFQfoCqF_@w-in(c2pNkpCKo6my8_yVs_Uj=zGVLKUT#^z^ z-)|f>)fuk#(@A>3(o0VqQ1$4+z_E9HCQ7R^ z30tu-(OIxDiiOEkGpXw&zReM}VP+C}bFAvU5%L?0cQ@?`fBSwH7!4o)d`OImPc+X< zrwk1#`^<8L8#>HOQb0pxt)HxXg%o|3x3nsPjSioaPqZ^lnSNOaJHg}1zqdDur0PoP zRVh{xV61JsNFuq`Xd6MtK*HtXN?NH20{)o}s_-I*YU7#=qn8b)kV`MS%A%ewrx<5I zY9{WpWlK^G^SP=5nvS-WEy+2%2}G?;#q01CSQ@%UJgw>}sHVEQip4`tToFyKHmwTV z-vWa!(`#8lj^drh)TLYVZLU!F!ak3OPw(qUajt(mO&u~ANUN%r3KUzV%k%|1=7Iat z5Pt`rL>P6u2G|qX<$)j~A0r2ZdE%y2n!@s>8}^KzEQEj6Kc?A%>r0ye>xB@wj|1Ob47`2EH4(rA(O{ zU}u2kj}N3&2?^3EQ{aT{?2g=~RLM;{)T7k%gI$^7qr`&%?-K{7Z|xhUKgd+!`-Yie zuE4Z_s?8kT>|npn6{66?E4$Pc2K(`?YTz3q(aigbu-ShRhKK|(f0cCh1&Q1?!Rr=v&a!K}wA-|$Gr{J~k~ z7@gS_x|i#V?>C5h_S4>+&Y9UC;Z@h2@kZgiJ|M%c)C38h@es^Y`p#a9|M_8mi3pR( z6*QJ0&b&7q+!3NCbBMs(x}XlEUyQp~0K9id;Wx1KycVf%ae(I8KJgjc!$0vE-NSwS zEu2^31P|2W6P)+j90blNtRJ5=DmAN?R}TD4!&z=N=@IeHhDTl-!_-e0hc?;+-;cCJ zm~zCBdd&GjPVt9?QcvkJQtf#Mv5mGLq7;pHYUils+`Yo8=kJB06UOcuYC;cMU2)oG zMH>rDE_p-R8=u3n)w%~+lE$>My@gq^RU(c_#Yk|`!Sjm$ug=Rfte#lnU+3im?EmV# zsQ)8&61KN9vov>gGIX)DxBI8_l58uFEQm1nXX|V=m@g=xsEFu>FsERj84_NVQ56PN z!biByA&vMXZd;f2LD`as@gWp{0NymGSG%BQYnYw6nfWRI`$p&Ub8b!_;Pjp%TsmXI zfGrv)2Ikh0e{6<_{jJk;U`7Zl+LFg){?(TM{#uQ_K{wp6!O_Bx33d!Brgr9~942)4 zchrS8Old{AF_&$zBx^bCTQ74ka9H84%F{rOzJ`rkJjSB_^^pZqe9`VQ^HyUpX_!ZA z+f0In>sw`>{d(L>oA+{4&zo5_^6t%TX0Gj0^M@u0@~^-f=4Gt9HMY&X&b`K%xjauF z8_!X>V|CrL;+a6gp zKd)6{;@wH+A{&U6?dAu>etSxBD)@5z;S~6%oQqH(uVW(Ajr>Dy{pPKUlD+ zFbjJ6c69Zum)+VkzfW(gW7%C{gU6X+a{LH?s2^BS64n$B%cf()0AWRUIbQPhQ|q|& z55=zLH=!8-f5HKjA|4`9M&54<=^^w{`bc~@pMec>@~;_k-6-b93So0uesmwYOL zmrx9lp%heN8h0j@P=!rO5=@h9UIZ^85wMay-2UO?xo>XOHLK<6Q|uyT6%*f4V!dYTC-$swh8fk{pCMlf5hw+9jV|?GlEBEAx zj#np5nqD`peZ6m5`&-xKetv((^8@xo*!!N3lmt=YUou<_xyn#yJp3Y#wf`tEP?IB4 z>Mq>31$Blx^|cr*L09CYlW3$Ek;PY`k@ToRobo6~q}E71Oxr##L$~JJ9_?1@As_if z`YlL&yDtoy733P&wytI4>Gd;vxHw2O@+@KgbPa)>3z8mMkyAS%Fna#8Sg!uWhMEubF;n{i3Ae4j{$p>dYj-^9?1ysjK~i0Q(4XUQE? zq8WLEcE@FsQ%hrS`3O$YbyPGkF6o;%&dxfHG?_n@Z&K4vR@ieBC{}cst~pIc4R0u& zj`QUL>5UQF@PgvVoBbRAtoQ_wyeeA9wsSN9mXX-dN^aFG=EB_B_b{U`BenI&D=;Fj zT!n`sy{aPu9YibsEpvrQ^0t(q&Inj%Pca%Yu&!K1ORT4wD6j-dc+{?5(JAouXgIy8 z%-H6Fbhd6%S=KCeIm`}PC!@`F>UKx&(#(Exk?s77w@&*`_tZ&sgzQ!_QK=DBnare8 z;)ocuEeZw)R1@{BuzGzIj$Z6EqM#s17Zv{q88!cq88!bXFpB=ZG^k$1C)OSWOnz4h zh&DA{Lx8q4*47TCo_gzx?MlHD(Bx{$87ha%T$XB*_{8uv@LhK>VV`UY=tPjwOandObAG0 z65^99S$7U)%^i%0Rnv*|IFjxg{!=`YHMJK^XV#j)p>*^S8FcuGV-BAwAU)a(e+)Wj z<=0$&0zB{usg@89sQBDI-|(HM1iz{8?zwn?5-k8jfM6Uf#vp^D4ozQhw#0tB@N(_V z5G#8|@Ta&(7#{whu<-X6VG66*t5~?Wlg0j8JGkpMEo%Sg1fExMxWXFTg2;1a+bNC~ zMiFaxTcU3ZKjv)V5kM}`LLzVunn%c$N*BoJj-NZ6`Q{g=3;*E#!f_{#*C?+ad~5zZ z=keRIuK5M;04KWI+Ycv(7YzExxp+b(xFaY3Z^kf3mPKNCd{OQbO%F%7nd8P(nBNon z_?lN|<`FF*oN)KZYNm_512Er;<8GEqpFWsK<1M&j{|B zo5C*08{%HJJyGfROq44Q!PMdxq^&J+j?ahYI=`%GLh<*U*BGQ36lvssxuhS-weUq^_|F7sRH2KqhQ2}MFKYfgn|}o{=of1QHP+(v0l0HYK}G+OiNO_D__5DAvd@{ul69am-m8ERsfZLSCNp9cTU% zmH*GrZ`geV`DBTGGoW+_>cFiEGR0sT5#0!Gq3u)$0>Q+2gNXQYFn7##$e~T?O6@UKnaPmHYrr;IL66 zpHCH6FCU(hv{CKW&}j6$b_zL?RWjo+BMls3=9G<#5Tzqzb=To%u9RQYw&j~}FJ@T0 zwqYi7d0bfhOvCF+KQ?e8GFX^6Wr;#sLd>z=9rOo+Sn!Gx#S!8{JZOiICy=>JL!*Db z?0=i<6a%%-Qb$_VMK#jDzwycH@RdM&ODTf(BM+(VE<)*OfvATsOZ?;*Z|+KHl#LYV zwB(~69*ivMM^es;_qv2a`F=yr7hG(h9F_QsJdxq1W);`Gg)XvElwdAOhjO9z zZr>li{sH_~k(_n9ib4ek0I-7t03iF%BB@~LVj<}4Y-(%tUl(nv+J`Z=I^xgjDynBP zN0jq=Yp@Y{EX@X*q%wsh^8JcPZT)X5xy=r1Yhrts;iZ@>npp;KAbS=u^ z7C^t_c%Z%wUF|lirC0D?_B+enX?Etl?DjuDbKmTMIivlD98rUKIU`CqV0Ocly#&IF zVJ8$a8*L_yNF&jX!-@&G+9c#)>ZeLLirXnS+DtWKjc8+nJ|uDRlm6xpN-+4*hewV+ zK>0BT%8ou*`H3UuqFuNnXC^;BIAixsF!~XP(TYBlVf14Qq4mS}s)|2ZF#71(dk7cV zj6Tw*_G9cDz}0~ zXB=I`eTPx>~gi%8(4o7@g1GNnp$hJ_%Mg1`VLZDvLJeHGr+zT1&yk_ z)dbBKq?T{~APy~$Nlig_@z&C!xIWPDo3m~uxHe!qrNb26;xt|ht-7c7np#s+cje~J zZ~taj5)DfMbEaGGQw!+3dN0G2S=fRaa3rl z7Osx|l1jjjIOhCoaPxPQt1`ZxtLxIkA`VmUHN|vTlJRWNz<2C9m^>k4usuSUG})b%|D<wP^rU?JNVjdb*1yWsZBE8HZC}Q5va#I zsBwfZp;FX)RpB3EoWZyd4Bs{TNmbQ{0Kzz-0SgBPl2=f6IWi{9_QZu%rTT_|l31Q_ zycR4qyR5Il(L|CofDAL(ez5(KmRFo@U&>^{qK1eq^QMA`FZE_d6`2iXL�H$uJM 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 Date: Sat, 25 May 2024 16:20:02 +0800 Subject: [PATCH 2/5] Switched submodule links and updated mods.toml --- .gitmodules | 3 +- build.gradle | 1 + mod_info/META-INF/mods.toml | 151 ++++++++++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 mod_info/META-INF/mods.toml diff --git a/.gitmodules b/.gitmodules index 3602e61..3c1d4b8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,4 @@ [submodule "BuildCraft"] path = BuildCraft - url = https://github.com/BuildCraft/BuildCraft.git + url = https://github.com/LRW-Calen/BuildCraft.git + branch = 8.0.x-1.16.5 diff --git a/build.gradle b/build.gradle index af4be14..37b9863 100755 --- a/build.gradle +++ b/build.gradle @@ -139,6 +139,7 @@ sourceSets { } resources { srcDir "resources" + srcDir "mod_info" srcDir "BuildCraft/buildcraft_resources" srcDir 'BuildCraft/buildcraft_resources_generated' srcDir "BuildCraft/BuildCraft-Localization" diff --git a/mod_info/META-INF/mods.toml b/mod_info/META-INF/mods.toml new file mode 100644 index 0000000..f28ec06 --- /dev/null +++ b/mod_info/META-INF/mods.toml @@ -0,0 +1,151 @@ +modLoader="javafml" +loaderVersion="[36,)" +license="Minecraft Mod Public License" +issueTrackerURL="" +[[mods]] +modId="buildcraftlib" +displayName="BuildCraft Lib" +version="7.99.24.9" +description="Library mod used by buildcraft." +credits="Created by SpaceToad" +logoFile="logo.png" +displayURL="http://www.mod-buildcraft.com/" +updateJSONURL="" +authors="SpaceToad, BuildCraft Team" + +[[mods]] +modId="buildcraftcore" +displayName="BuildCraft" +version="7.99.24.9" +description="Extending Minecraft with pipes, auto-crafting, quarries, engines and much more!" +credits="Created by SpaceToad" +logoFile="logo.png" +displayURL="http://www.mod-buildcraft.com/" +updateJSONURL="" +authors="SpaceToad, BuildCraft Team" + +[[mods]] +modId="buildcraftbuilders" +displayName="BuildCraft Builders" +version="7.99.24.9" +description="Extending Minecraft with pipes, auto-crafting, quarries, engines and much more! (Builders Component)" +credits="Created by SpaceToad" +logoFile="logo.png" +displayURL="http://www.mod-buildcraft.com/" +updateJSONURL="" +authors="SpaceToad, BuildCraft Team" + +[[mods]] +modId="buildcraftenergy" +displayName="BuildCraft Energy" +version="7.99.24.9" +description="Extending Minecraft with pipes, auto-crafting, quarries, engines and much more! (Energy Component)" +credits="Created by SpaceToad" +logoFile="logo.png" +displayURL="http://www.mod-buildcraft.com/" +updateJSONURL="" +authors="SpaceToad, BuildCraft Team" + +[[mods]] +modId="buildcraftfactory" +displayName="BuildCraft Factory" +version="7.99.24.9" +description="Extending Minecraft with pipes, auto-crafting, quarries, engines and much more! (Factory Component)" +credits="Created by SpaceToad" +logoFile="logo.png" +displayURL="http://www.mod-buildcraft.com/" +updateJSONURL="" +authors="SpaceToad, BuildCraft Team" + +[[mods]] +modId="buildcraftsilicon" +displayName="BuildCraft Silicon" +version="7.99.24.9" +description="Extending Minecraft with pipes, auto-crafting, quarries, engines and much more! (Silicon Component)" +credits="Created by SpaceToad" +logoFile="logo.png" +displayURL="http://www.mod-buildcraft.com/" +updateJSONURL="" +authors="SpaceToad, BuildCraft Team" + +[[mods]] +modId="buildcrafttransport" +displayName="BuildCraft Transport" +version="7.99.24.9" +description="Extending Minecraft with pipes, auto-crafting, quarries, engines and much more! (Transport Component)" +credits="Created by SpaceToad" +logoFile="logo.png" +displayURL="http://www.mod-buildcraft.com/" +updateJSONURL="" +authors="SpaceToad, BuildCraft Team" + +[[mods]] +modId="buildcraftrobotics" +displayName="BuildCraft Robotics" +version="7.99.24.9" +description="Extending Minecraft with pipes, auto-crafting, quarries, engines and much more! (Robotics Component)" +credits="Created by SpaceToad" +logoFile="logo.png" +displayURL="http://www.mod-buildcraft.com/" +updateJSONURL="" +authors="SpaceToad, BuildCraft Team" + +[[mods]] +modId="buildcraftcompat" +displayName="BuildCraft Compat" +version="7.99.24.9" +description="Compatibility add-on for BuildCraft" +credits="Created by asie" +logoFile="logo.png" +displayURL="http://www.mod-buildcraft.com/" +updateJSONURL="" +authors="BuildCraft Team" + +[[dependencies.buildcraftcore]] + modId="forge" + mandatory=true + versionRange="[36,)" + ordering="NONE" + side="BOTH" +[[dependencies.buildcraftcore]] + modId="minecraft" + mandatory=true + versionRange="[1.16,1.17)" + ordering="NONE" + side="BOTH" +[[dependencies.buildcraftcore]] + modId="buildcraftlib" + mandatory=true + versionRange="[0.0.0,)" + ordering="AFTER" + side="BOTH" +[[dependencies.buildcraftenergy]] + modId="buildcraftcore" + mandatory=true + versionRange="[0.0.0,)" + ordering="AFTER" + side="BOTH" +[[dependencies.buildcraftbuilders]] + modId="buildcraftcore" + mandatory=true + versionRange="[0.0.0,)" + ordering="AFTER" + side="BOTH" +[[dependencies.buildcrafttransport]] + modId="buildcraftcore" + mandatory=true + versionRange="[0.0.0,)" + ordering="AFTER" + side="BOTH" +[[dependencies.buildcraftrobotics]] + modId="buildcraftcore" + mandatory=true + versionRange="[0.0.0,)" + ordering="AFTER" + side="BOTH" +[[dependencies.buildcraftcompat]] + modId="buildcraftcore" + mandatory=true + versionRange="[0.0.0,)" + ordering="AFTER" + side="BOTH" From d4745b56628a0a908a6cd000497935c6f7878842 Mon Sep 17 00:00:00 2001 From: LRW-Calen Date: Sat, 25 May 2024 17:03:37 +0800 Subject: [PATCH 3/5] Updated submodule --- BuildCraft | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BuildCraft b/BuildCraft index 656b0a0..14ad775 160000 --- a/BuildCraft +++ b/BuildCraft @@ -1 +1 @@ -Subproject commit 656b0a00a04bf61ebd9f39f6c3e44eac2818b1ec +Subproject commit 14ad77537daed6df2378204b8b36cebbf41236a6 From d20800bb8e4d6ee63d68f3a42ba3e066d35dd811 Mon Sep 17 00:00:00 2001 From: LRW-Calen Date: Sat, 25 May 2024 17:30:46 +0800 Subject: [PATCH 4/5] Updated submodule --- BuildCraft | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BuildCraft b/BuildCraft index 14ad775..bafa041 160000 --- a/BuildCraft +++ b/BuildCraft @@ -1 +1 @@ -Subproject commit 14ad77537daed6df2378204b8b36cebbf41236a6 +Subproject commit bafa041e116173da5b8f343a14271fc34f84c2c9 From 05659e851f9812fdf3a3391192244c00454be427 Mon Sep 17 00:00:00 2001 From: LRW-Calen Date: Sun, 2 Jun 2024 00:02:45 +0800 Subject: [PATCH 5/5] Updated submodule --- .gitmodules | 2 +- BuildCraft | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 3c1d4b8..c1278a7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "BuildCraft"] path = BuildCraft - url = https://github.com/LRW-Calen/BuildCraft.git + url = https://github.com/CalenXwX/BuildCraft.git branch = 8.0.x-1.16.5 diff --git a/BuildCraft b/BuildCraft index bafa041..75c0b79 160000 --- a/BuildCraft +++ b/BuildCraft @@ -1 +1 @@ -Subproject commit bafa041e116173da5b8f343a14271fc34f84c2c9 +Subproject commit 75c0b79cdd5695f35484378afd8bb12777c3296a