From 37d2cee58ac660675e9d422d317ee544a93f5737 Mon Sep 17 00:00:00 2001 From: CalenXwX Date: Wed, 18 Dec 2024 01:31:35 +0800 Subject: [PATCH 1/9] Forge 1.20.1 --- .gitignore | 26 +- .gitmodules | 3 +- build.gradle | 606 ++++++++++++------ build.properties | 28 +- common/buildcraft/compat/BCCompat.java | 199 +++--- common/buildcraft/compat/BCCompatBlocks.java | 22 + .../buildcraft/compat/CompatModuleBase.java | 5 +- common/buildcraft/compat/CompatUtils.java | 39 +- .../datagen/BCCompatDataGenerators.java | 49 ++ .../datagen/CompatBlockStateGenerator.java | 26 + .../datagen/CompatItemModelGenerator.java | 20 + .../module/crafttweaker/AssemblyTable.java | 251 ++++++-- .../crafttweaker/BCRecipeComponents.java | 49 ++ .../module/crafttweaker/CombustionEngine.java | 315 +++++---- .../CompatModuleCraftTweaker.java | 30 +- .../compat/module/crafttweaker/Coolant.java | 185 ++++++ .../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 ------ .../module/forge/BlockPowerConvertor.java | 17 + .../module/forge/TilePowerConvertor.java | 276 ++++++++ .../ic2/CompatModuleIndustrialCraft2.java | 27 +- .../compat/module/jei/BCPluginJEI.java | 282 +++++--- .../CategoryCombustionEngine.java | 166 +++-- .../HandlerCombustionEngine.java | 19 - .../WrapperCombustionEngine.java | 110 ---- .../energy/combustionengine/package-info.java | 5 +- .../module/jei/factory/CategoryCoolable.java | 137 +++- .../module/jei/factory/CategoryDistiller.java | 141 ++-- .../module/jei/factory/CategoryHeatable.java | 131 +++- .../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 | 5 +- .../module/jei/gui/GuiHandlerBuildCraft.java | 48 ++ .../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 | 153 +++-- .../jei/silicon/CategoryIntegrationTable.java | 140 ++-- .../jei/silicon/HandlerIntegrationTable.java | 38 -- .../compat/module/jei/silicon/Utils.java | 12 +- .../jei/silicon/WrapperAssemblyTable.java | 83 --- .../jei/silicon/WrapperIntegrationTable.java | 93 --- .../module/jei/silicon/package-info.java | 5 +- .../AdvancedCraftingItemsTransferHandler.java | 53 +- .../AssemblyTableTransferHandler.java | 30 +- .../AutoCraftItemsTransferHandler.java | 81 ++- .../jei/transferhandlers/package-info.java | 5 +- .../compat/module/rei/BCPluginREI.java | 110 ++++ .../compat/module/rei/ReiUtils.java | 61 ++ .../CategoryCombustionEngine.java | 114 ++++ .../DisplayCombustionEngine.java | 48 ++ .../module/rei/factory/CategoryCoolable.java | 97 +++ .../module/rei/factory/CategoryDistiller.java | 105 +++ .../module/rei/factory/CategoryHeatable.java | 87 +++ .../module/rei/factory/DisplayCoolable.java | 35 + .../rei/factory/DisplayDistillation.java | 39 ++ .../module/rei/factory/DisplayHeatable.java | 35 + .../module/rei/gui/GuiHandlerBuildCraft.java | 32 + .../rei/silicon/CategoryAssemblyTable.java | 102 +++ .../rei/silicon/CategoryIntegrationTable.java | 4 + .../module/rei/silicon/DisplayAssembly.java | 36 ++ .../rei/silicon/DisplayIntegration.java | 29 + .../module/theoneprobe/BCPluginTOP.java | 132 ++-- .../theoneprobe/CompatModuleTheOneProbe.java | 11 +- .../waila/AssemblyCraftDataProvider.java | 63 ++ .../module/waila/AutoCraftDataProvider.java | 128 ++-- .../module/waila/BaseWailaDataProvider.java | 79 +-- .../compat/module/waila/HWYLAPlugin.java | 71 +- .../module/waila/LaserTargetDataProvider.java | 80 ++- .../module/waila/MjStorageDataProvider.java | 64 ++ .../buildcraft/compat/network/CompatGui.java | 304 ++++----- .../compat/network/IGuiCreator.java | 25 +- gradle.properties | 38 ++ gradle/wrapper/gradle-wrapper.jar | Bin 53556 -> 62076 bytes gradle/wrapper/gradle-wrapper.properties | 12 +- gradlew | 297 +++++---- gradlew.bat | 62 +- mod_info/META-INF/mods.toml | 151 +++++ 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 | 65 ++ .../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 | 60 ++ resources/mcmod.info | 16 - settings.gradle | 13 + 105 files changed, 4880 insertions(+), 2859 deletions(-) create mode 100644 common/buildcraft/compat/BCCompatBlocks.java create mode 100644 common/buildcraft/compat/datagen/BCCompatDataGenerators.java create mode 100644 common/buildcraft/compat/datagen/CompatBlockStateGenerator.java create mode 100644 common/buildcraft/compat/datagen/CompatItemModelGenerator.java create mode 100644 common/buildcraft/compat/module/crafttweaker/BCRecipeComponents.java 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 create mode 100644 common/buildcraft/compat/module/forge/BlockPowerConvertor.java create mode 100644 common/buildcraft/compat/module/forge/TilePowerConvertor.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/rei/BCPluginREI.java create mode 100644 common/buildcraft/compat/module/rei/ReiUtils.java create mode 100644 common/buildcraft/compat/module/rei/energy/combustionengine/CategoryCombustionEngine.java create mode 100644 common/buildcraft/compat/module/rei/energy/combustionengine/DisplayCombustionEngine.java create mode 100644 common/buildcraft/compat/module/rei/factory/CategoryCoolable.java create mode 100644 common/buildcraft/compat/module/rei/factory/CategoryDistiller.java create mode 100644 common/buildcraft/compat/module/rei/factory/CategoryHeatable.java create mode 100644 common/buildcraft/compat/module/rei/factory/DisplayCoolable.java create mode 100644 common/buildcraft/compat/module/rei/factory/DisplayDistillation.java create mode 100644 common/buildcraft/compat/module/rei/factory/DisplayHeatable.java create mode 100644 common/buildcraft/compat/module/rei/gui/GuiHandlerBuildCraft.java create mode 100644 common/buildcraft/compat/module/rei/silicon/CategoryAssemblyTable.java create mode 100644 common/buildcraft/compat/module/rei/silicon/CategoryIntegrationTable.java create mode 100644 common/buildcraft/compat/module/rei/silicon/DisplayAssembly.java create mode 100644 common/buildcraft/compat/module/rei/silicon/DisplayIntegration.java create mode 100644 common/buildcraft/compat/module/waila/AssemblyCraftDataProvider.java create mode 100644 common/buildcraft/compat/module/waila/MjStorageDataProvider.java create mode 100644 gradle.properties create mode 100644 mod_info/META-INF/mods.toml 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..adcedd9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,26 +1,46 @@ -#eclipse +# eclipse .project .classpath .metadata org.* bin *.launch +.settings +eclipse -#idea +# idea *.iml *.ipr *.iws .idea out -#gradle +# gradle build .gradle +modules libs #runtime run +run_server classes #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/.gitmodules b/.gitmodules index 3602e61..7730ed0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,4 @@ [submodule "BuildCraft"] path = BuildCraft - url = https://github.com/BuildCraft/BuildCraft.git + url = https://github.com/CalenXwX/BuildCraft.git + branch = 8.0.x-1.20.1 diff --git a/build.gradle b/build.gradle index 95cf589..7c7dce2 100755 --- a/build.gradle +++ b/build.gradle @@ -1,30 +1,26 @@ -// DON'T TOUCH THE BUILDSCRIPT[] BLOCK -// its special, and it is only there to make ForgeGradle work correctly. - buildscript { repositories { + // These repositories are only for Gradle plugins, put any other repositories in the repository core further below + 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 group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '5.1.+', changing: true + // Mixin + classpath 'org.spongepowered:mixingradle:0.7.+' classpath "org.ajoberstar:grgit:2.2.1" } } -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 +plugins { + id 'eclipse' + id 'idea' + id 'maven-publish' + id 'net.minecraftforge.gradle' version '[6.0,6.2)' +} +apply plugin: 'net.minecraftforge.gradle' +// Mixin +apply plugin: 'org.spongepowered.mixin' apply plugin: "org.ajoberstar.grgit" ext.configFile = file "build.properties" @@ -44,97 +40,141 @@ 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/" } +// compatModInfo = file("resources/mods.toml") +// mainModInfo = file("BuildCraft/buildcraft_resources/mods.toml") + compatModInfo = file("mod_info/META-INF/mods.toml").readLines() + mainModInfo = file("BuildCraft/mod_info/META-INF/mods.toml").readLines() } -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}" -} +// Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17. +java.toolchain.languageVersion = JavaLanguageVersion.of(17) +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 + // The mappings can be changed at any time and must be in the following format. + // Channel: Version: + // official MCVersion Official field/method names from Mojang mapping files + // parchment YYYY.MM.DD-MCVersion Open community-sourced parameter names and javadocs layered on top of official + // + // You must be aware of the Mojang license when using the 'official' or 'parchment' mappings. + // See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md + // + // Parchment is an unofficial project maintained by ParchmentMC, separate from MinecraftForge + // Additional setup is needed to use their mappings: https://parchmentmc.org/docs/getting-started + // + // 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: config.mappings_channel, version: config.mappings_version + + // When true, this property will have all Eclipse/IntelliJ IDEA run configurations run the "prepareX" task for the given run configuration before launching the game. + // In most cases, it is not necessary to enable. + // enableEclipsePrepareRuns = true + // enableIdeaPrepareRuns = true + + // This property allows configuring Gradle's ProcessResources task(s) to run on IDE output locations before launching the game. + // It is REQUIRED to be set to true for this template to function. + // See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html + copyIdeResources = true + + // When true, this property will add the folder name of all declared run configurations to generated IDE run configurations. + // The folder name can be set on a run configuration using the "folderName" property. + // By default, the folder name of a run configuration is the name of the Gradle project containing it. + // generateRunFolders = true + + // This property enables access transformers for use in development. + // They will be applied to the Minecraft artifact. + // The access transformer file can be anywhere in the project. + // However, it must be at "META-INF/accesstransformer.cfg" in the final mod jar to be loaded by Forge. + // This default location is a best practice to automatically put the file in the right place in the final jar. + // See https://docs.minecraftforge.net/en/latest/advanced/accesstransformers/ for more information. + accessTransformer = file('BuildCraft/buildcraft_resources/META-INF/accesstransformer.cfg') def separate = Boolean.getBoolean("build_compat_only") if (separate) { project.version = config.compat_version } else { - project.version = config.mod_version; +// project.version = config.mod_version; + project.version = config.compat_version + "-" + config.mc_version + "-" + new Date().format("yyyy-MM-dd'T'HH-mm-ssZ") } - 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) +// 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" +// } +// } +// +// // 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 + + // Default run configurations. + // These can be tweaked, removed, or duplicated as needed. + runs { + // applies to all the run configs below + configureEach { + workingDirectory project.file('run') + + // Recommended logging data for a userdev environment + // The markers can be added/remove as needed separated by commas. + // "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 { + "${mod_id}" { + source sourceSets.main + } + } } - } else { - if (addVersionDetails) { - project.version += "-SNAPSHOT" + + client { + // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. + property 'forge.enabledGameTestNamespaces', mod_id + } + + server { + workingDirectory project.file('run_server') + property 'forge.enabledGameTestNamespaces', mod_id + args '--nogui' } - } - // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. + // This run config launches GameTestServer and runs all registered gametests, then exits. + // By default, the server will crash when no gametests are provided. + // The gametest system is also enabled by default for other run configs under the /test command. + gameTestServer { + property 'forge.enabledGameTestNamespaces', mod_id + } - // 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 + data { + // example of overriding the workingDirectory set in configureEach above + workingDirectory project.file('run-data') - useDepAts = true + // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. + args '--mod', mod_id, '--all', '--output', file('BuildCraft/buildcraft_resources_generated/'), '--existing', file('BuildCraft/buildcraft_resources/') + } + } } compileJava { @@ -157,151 +197,335 @@ task setupSubProjects(dependsOn: "BuildCraft:sub_projects:expression:generateSou // Just an inter-dependency task } -eclipseClasspath.dependsOn setupSubProjects -ideaModule.dependsOn setupSubProjects -compileApiJava.dependsOn setupSubProjects +//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 "mod_info" srcDir "BuildCraft/buildcraft_resources" + srcDir 'BuildCraft/buildcraft_resources_generated' + srcDir "BuildCraft/BuildCraft-Localization" srcDir "BuildCraft/BuildCraftGuide/guide_resources" - exclude "pack.png" // exclude from the guide repo - exclude "pack.mcmeta" // exclude from the guide repo + exclude "**/.md" // exclude readme from localization repo + exclude "pack.png" + exclude '.cache' + exclude "pack.mcmeta_" + // 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 { url = 'https://mvnrepository.com/artifact/net.sf.trove4j/trove4j' } + + maven { + name 'prog' + url 'https://dvs1.progwml6.com/files/maven' + content { + includeGroup 'mezz.jei' + } + } + 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/" + } + // JEI + maven { + // location of a maven mirror for JEI files, as a fallback + name = "ModMaven" + url = "https://modmaven.dev" + } + // CraftTweaker JEI + maven { + url = 'https://maven.blamejared.com' + name = 'BlameJared Maven' + } + // TOP + maven { + url "https://maven.k-4u.nl/" + content { + includeGroup "mcjty" + } + } + // REI + maven { + url "https://maven.shedaniel.me" } } -def createAllModInfo() { - return new File("$projectDir/build/processing/compat-all/mcmod.info") +//// Mixin +mixin { + add sourceSets.main, "refmap.buildcraft.json" + config 'mixins.buildcraft.json' + mixin.env.remapRefMap = true + debug = true + debug.verbose = true + debug.export = true } -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]; - } - 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 - } -} +dependencies { + // Specify the version of Minecraft to use. + // Any artifact can be supplied so long as it has a "userdev" classifier artifact and is a compatible patcher artifact. + // The "userdev" classifier will be requested and setup by ForgeGradle. + // If the group id is "net.minecraft" and the artifact id is one of ["client", "server", "joined"], + // then special handling is done to allow a setup of a vanilla dependency without the use of an external repository. + minecraft "net.minecraftforge:forge:${config.mc_version}-${config.forge_version}" -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") + // Examples using mod jars from ./libs -// 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 -} + implementation fg.deobf("mezz.jei:jei-${config.mc_version}-forge:${config.jei_version}") -task compatJar(type: Jar, dependsOn:reobfJar) { - destinationDir = modulesDir - appendix = "compat" - version = project.version + implementation fg.deobf("me.shedaniel.cloth:cloth-config-forge:${config.cloth_config_version}") + implementation fg.deobf("dev.architectury:architectury-forge:${config.architectury_version}") + implementation fg.deobf("me.shedaniel:RoughlyEnoughItems-forge:${config.rei_version}") - from(project.ext.jarFile) { - includes.addAll("**") - } -} + implementation fg.deobf("curse.maven:jade-324717:" + config.jade_id) -task allJar(type: Jar, dependsOn: [reobfJar, writeAllModInfo]) { - destinationDir = libsDir - appendix = "all" - version = project.version + implementation(fg.deobf('com.blamejared.crafttweaker:CraftTweaker-forge-1.20.1:14.0.44')) - from(createAllModInfo().parentFile) - from(project.ext.jarFile) { - includes.addAll("**") - exclude("mcmod.info") + implementation fg.deobf("curse.maven:the-one-probe-245211:" + config.top_id) + + implementation "net.sf.trove4j:trove4j:3.0.3" + + jarJar(group: 'net.sf.trove4j', name: 'trove4j', version: '[3.0.3,)') { + jarJar.pin(it, '3.0.3') } -} -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' - from(createAllModInfo().parentFile) - from(unzippedSourceJar) { - includes.add("**") - exclude("mcmod.info") + annotationProcessor 'org.spongepowered:mixin:0.8.5:processor' +} + +// This block of code expands all declared replace properties in the specified resource targets. +// A missing property will result in an error. Properties are expanded using ${} Groovy notation. +// When "copyIdeResources" is enabled, this will also run before the game launches in IDE environments. +// See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html +tasks.named('processResources', ProcessResources).configure { + var replaceProperties = [ + minecraft_version : config.mc_version, + minecraft_version_range: minecraft_version_range, + forge_version : config.forge_version, + forge_version_range : forge_version_range, + loader_version_range : loader_version_range, + mod_id : mod_id, + mod_name : mod_name, + mod_license : mod_license, + mod_version : mod_version, + mod_authors : mod_authors, + mod_description : mod_description, + ] + inputs.properties replaceProperties + + filesMatching(['META-INF/mods.toml', 'pack.mcmeta']) { + expand replaceProperties + [project: project] } } +//processResources { +// // replace stuff in mcmod.info, nothing else +// from(sourceSets.main.resources.srcDirs) { +// include 'mcmod.info' +// +// // replace version and mcversion +// // ${version} and ${mcversion} are the exact strings being replaced +// expand 'version': project.version, 'mcversion': project.minecraft.version, 'modid': config.modid +// } +// +// // copy everything else, that's not the mcmod.info +// from(sourceSets.main.resources.srcDirs) { +// exclude 'mcmod.info' +// exclude 'pack.mcmeta' +// exclude 'pack.png' +// } +//} + +// Example for how to get properties into the manifest for reading at runtime. +tasks.named('jar', Jar).configure { + 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" + ]) + } -build.dependsOn compatJar, allJar, allSrcJar + // This is the preferred method to reobfuscate your jar file + finalizedBy 'reobfJar' +} +//def createAllModInfo() { +// return new File("$projectDir/build/processing/compat-all/mods.toml") +//} + +//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]; +// } +// elements += compatModInfo[0]; +// String prettyPrinted = elements.join("\r\n") +// prettyPrinted = prettyPrinted.replace("\$version", project.version) +// prettyPrinted = prettyPrinted.replace("\${mcversion}", project.minecraft.version) +// temp.write(prettyPrinted) +// return temp +// } +//} + +//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") + +//// 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 +//} + +//task allJar(type: Jar, dependsOn: ["reobfJar", "writeAllModInfo"]) { +// destinationDir = libsDir +// appendix = "all" +// version = project.version +// +// from(createAllModInfo().parentFile) +// from(project.ext.jarFile) { +// includes.addAll("**") +// exclude("mcmod.info") +// } +//} + +//task allSrcJar(type: Jar, dependsOn:[reobfJar, writeAllModInfo, unzipSourceJar]) { +// destinationDir = libsDir +// appendix = "all" +// classifier = "sources" +// +// from(createAllModInfo().parentFile) +// from(unzippedSourceJar) { +// includes.add("**") +// exclude("mcmod.info") +// } +//} + +//build.dependsOn compatJar, allJar, allSrcJar + +//task compatJar(type: Jar, dependsOn:reobfJar) { +// destinationDir = modulesDir +// appendix = "compat" +// version = project.version +// +// from(project.ext.jarFile) { +// includes.addAll("**") +// } +//} + +// 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: +// tasks.named('publish').configure { +// dependsOn 'reobfJar' +// } + +// Example configuration to allow publishing using the maven-publish plugin publishing { + publications { + register('mavenJava', MavenPublication) { + artifact jar + } +// 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 +// +// artifact allSrcJar +// } + } repositories { maven { +// url "file://${project.projectDir}/mcmodsrepo" url System.getenv("MAVEN_DIR") ?: "$projectDir/build/maven" } } - 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 +tasks.withType(JavaCompile).configureEach { + options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation +} - artifact allSrcJar - } - } +jar.enabled = true + +// enable Jar-in-Jar +jarJar.enable() + +tasks.named('jarJar') { + // ... } diff --git a/build.properties b/build.properties index 66c247b..eb0b2a6 100644 --- a/build.properties +++ b/build.properties @@ -1,8 +1,22 @@ -compat_version=7.99.15 +mc_version=1.20.1 +forge_version=47.3.12 +mappings_channel=official +mappings_version=1.20.1 +mod_version=7.99.24.9 -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 -ic2_version=2.8.221-ex112 +#compat_version=7.99.15 +compat_version=7.99.24.9 + +jade_api_id=3803228 +jade_id=5876199 +#jei_id=5846810 +jei_version=15.20.0.105 +cloth_config_version=11.1.136 +architectury_version=9.2.14 +rei_version=12.1.785 +top_id=5159287 +#crafttweaker_id=5880672 +crafttweaker_version=14.0.44 + +#forestry_version=5.7.0.236 +#ic2_version=2.8.221-ex112 diff --git a/common/buildcraft/compat/BCCompat.java b/common/buildcraft/compat/BCCompat.java index 72fdbaa..e3ad066 100644 --- a/common/buildcraft/compat/BCCompat.java +++ b/common/buildcraft/compat/BCCompat.java @@ -1,53 +1,47 @@ -/* - * 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; - -//@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 buildcraft.core.BCCore; +import buildcraft.lib.config.ConfigCategory; +import buildcraft.lib.config.Configuration; +import buildcraft.lib.config.EnumRestartRequirement; +import buildcraft.lib.registry.RegistryConfig; +import buildcraft.lib.registry.TagManager; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; +import net.minecraftforge.fml.event.lifecycle.FMLConstructModEvent; +import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Consumer; + +//@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,17 +49,29 @@ 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<>(); + + public static Configuration config; - private static void offerAndPreInitModule(final CompatModuleBase module) { + 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)) { + String _modules = "modules"; + ConfigCategory prop = config + .define(_modules, + "", + EnumRestartRequirement.NONE, + cModId, true); + if (prop.get()) { modules.put(cModId, module); + moduleConfigs.put(cModId, prop); BCLog.logger.info("[compat] + " + cModId); module.preInit(); } else { @@ -76,9 +82,16 @@ private static void offerAndPreInitModule(final CompatModuleBase module) { } } - @Mod.EventHandler - public static void preInit(final FMLPreInitializationEvent evt) { + @SubscribeEvent + public static void preInit(FMLConstructModEvent evt) { + // Calen + RegistryConfig.useOtherModConfigFor(MODID, BCCore.MODID); + // Start config + BCModules module = BCModules.COMPAT; + config = new Configuration(module); + + // init BCLog.logger.info(""); BCLog.logger.info("Starting BuildCraftCompat " + VERSION); BCLog.logger.info("Copyright (c) the BuildCraft team, 2011-2017"); @@ -94,54 +107,72 @@ 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); + // Calen + BCCompatBlocks.fmlPreInit(); + } - // 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); - // } + private static final TagManager tagManager = new TagManager(); + + static { + startBatch(); + + registerTag("item.block.power_convertor").reg("power_convertor").locale("power_convertor"); + registerTag("block.power_convertor").reg("power_convertor").locale("power_convertor"); + registerTag("tile.power_convertor").reg("power_convertor"); + + endBatch(TagManager.prependTags("buildcraftcompat:", TagManager.EnumTagType.REGISTRY_NAME) + .andThen(TagManager.setTab("buildcraft.main")) + ); + } + + private static TagManager.TagEntry registerTag(String id) { + return tagManager.registerTag(id); + } + + private static void startBatch() { + tagManager.startBatch(); + } + + private static void endBatch(Consumer consumer) { + tagManager.endBatch(consumer); + } } diff --git a/common/buildcraft/compat/BCCompatBlocks.java b/common/buildcraft/compat/BCCompatBlocks.java new file mode 100644 index 0000000..1036710 --- /dev/null +++ b/common/buildcraft/compat/BCCompatBlocks.java @@ -0,0 +1,22 @@ +package buildcraft.compat; + +import buildcraft.compat.module.forge.BlockPowerConvertor; +import buildcraft.compat.module.forge.TilePowerConvertor; +import buildcraft.lib.block.BlockPropertiesCreator; +import buildcraft.lib.registry.RegistrationHelper; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraftforge.registries.RegistryObject; + +public class BCCompatBlocks { + public static final RegistrationHelper HELPER = new RegistrationHelper(BCCompat.MODID); + public static final RegistryObject powerConvertor; + public static final RegistryObject> powerConvertorTile; + + static { + powerConvertor = HELPER.addBlockAndItem("block.power_convertor", BlockPropertiesCreator.metal(), BlockPowerConvertor::new); + powerConvertorTile = HELPER.registerTile("tile.power_convertor", TilePowerConvertor::new, powerConvertor); + } + + public static void fmlPreInit() { + } +} 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..b3550b5 100644 --- a/common/buildcraft/compat/CompatUtils.java +++ b/common/buildcraft/compat/CompatUtils.java @@ -1,29 +1,29 @@ package buildcraft.compat; -import java.util.List; - +import buildcraft.compat.network.IGuiCreator; +import buildcraft.lib.misc.StackUtil; +import buildcraft.lib.tile.item.ItemHandlerSimple; import com.google.common.collect.Lists; - -import net.minecraft.item.ItemStack; - +import net.minecraft.world.item.ItemStack; import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.CapabilityManager; +import net.minecraftforge.common.capabilities.CapabilityToken; +import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; -import buildcraft.api.core.CapabilitiesHelper; - -import buildcraft.lib.tile.item.ItemHandlerSimple; - -import buildcraft.compat.network.IGuiCreator; +import java.util.List; +@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD, modid = BCCompat.MODID) public class CompatUtils { + public static final Capability CAP_GUI_CREATOR = CapabilityManager.get(new CapabilityToken<>() { + }); - 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 +32,8 @@ public static List compactInventory(ItemHandlerSimple inventory) { boolean handled = false; for (ItemStack existing : stacks) { - if (existing.isItemEqual(stack)) { +// if (existing.isItemEqual(stack)) + if (StackUtil.isSameItemSameDamage(existing, stack)) { existing.grow(stack.getCount()); handled = true; break; @@ -45,4 +46,10 @@ public static List compactInventory(ItemHandlerSimple inventory) { return stacks; } + + // Calen + @SubscribeEvent + public static void registerCapability(RegisterCapabilitiesEvent event) { + event.register(IGuiCreator.class); + } } diff --git a/common/buildcraft/compat/datagen/BCCompatDataGenerators.java b/common/buildcraft/compat/datagen/BCCompatDataGenerators.java new file mode 100644 index 0000000..6dff9db --- /dev/null +++ b/common/buildcraft/compat/datagen/BCCompatDataGenerators.java @@ -0,0 +1,49 @@ +package buildcraft.compat.datagen; + +import buildcraft.api.core.BCLog; +import buildcraft.core.BCCore; +import net.minecraft.data.DataGenerator; +import net.minecraftforge.common.data.ExistingFileHelper; +import net.minecraftforge.data.event.GatherDataEvent; +import net.minecraftforge.data.loading.DatagenModLoader; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +import java.lang.reflect.Field; +import java.util.List; + +@Mod.EventBusSubscriber(modid = BCCore.MODID, bus = Mod.EventBusSubscriber.Bus.MOD) +public class BCCompatDataGenerators { + @SubscribeEvent + public static void onGatherData(GatherDataEvent event) { + DataGenerator generator = event.getGenerator(); + ExistingFileHelper existingFileHelper = event.getExistingFileHelper(); + DataGenerator.PackGenerator packGenerator = generator.getVanillaPack(true); + + // BlockState and Block Model + packGenerator.addProvider(packOutput -> new CompatBlockStateGenerator(packOutput, existingFileHelper)); + + // Item Model + packGenerator.addProvider(packOutput -> new CompatItemModelGenerator(packOutput, existingFileHelper)); + + // Calen 1.20.1 + enableShouldExecute(generator); + } + + // Calen 1.20.1 for datagen + private static void enableShouldExecute(DataGenerator generator) { + try { + Field f_dataGeneratorConfig = DatagenModLoader.class.getDeclaredField("dataGeneratorConfig"); + f_dataGeneratorConfig.setAccessible(true); + GatherDataEvent.DataGeneratorConfig config = (GatherDataEvent.DataGeneratorConfig) f_dataGeneratorConfig.get(null); + Field f_generators = GatherDataEvent.DataGeneratorConfig.class.getDeclaredField("generators"); + f_generators.setAccessible(true); + List generators = (List) f_generators.get(config); + if (!generators.contains(generator)) { + generators.add(generator); + } + } catch (Exception e) { + BCLog.logger.error(e); + } + } +} diff --git a/common/buildcraft/compat/datagen/CompatBlockStateGenerator.java b/common/buildcraft/compat/datagen/CompatBlockStateGenerator.java new file mode 100644 index 0000000..07b01c4 --- /dev/null +++ b/common/buildcraft/compat/datagen/CompatBlockStateGenerator.java @@ -0,0 +1,26 @@ +package buildcraft.compat.datagen; + +import buildcraft.compat.BCCompat; +import buildcraft.compat.BCCompatBlocks; +import buildcraft.datagen.base.BCBaseBlockStateGenerator; +import net.minecraft.data.PackOutput; +import net.minecraftforge.client.model.generators.ConfiguredModel; +import net.minecraftforge.common.data.ExistingFileHelper; + +public class CompatBlockStateGenerator extends BCBaseBlockStateGenerator { + public CompatBlockStateGenerator(PackOutput output, ExistingFileHelper exFileHelper) { + super(output, BCCompat.MODID, exFileHelper); + } + + @Override + protected void registerStatesAndModels() { + // power_convertor + getVariantBuilder(BCCompatBlocks.powerConvertor.get()).forAllStates(s -> + ConfiguredModel.builder().modelFile( + models().withExistingParent("buildcraftcompat:block/power_convertor", CUBE_ALL) + .texture("all", "buildcraftcompat:block/power_convertor") + ) + .build() + ); + } +} diff --git a/common/buildcraft/compat/datagen/CompatItemModelGenerator.java b/common/buildcraft/compat/datagen/CompatItemModelGenerator.java new file mode 100644 index 0000000..3f43044 --- /dev/null +++ b/common/buildcraft/compat/datagen/CompatItemModelGenerator.java @@ -0,0 +1,20 @@ +package buildcraft.compat.datagen; + +import buildcraft.compat.BCCompat; +import buildcraft.compat.BCCompatBlocks; +import buildcraft.datagen.base.BCBaseItemModelGenerator; +import net.minecraft.data.PackOutput; +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.common.data.ExistingFileHelper; + +public class CompatItemModelGenerator extends BCBaseItemModelGenerator { + public CompatItemModelGenerator(PackOutput output, ExistingFileHelper existingFileHelper) { + super(output, BCCompat.MODID, existingFileHelper); + } + + @Override + protected void registerModels() { + // power_convertor + withExistingParent(BCCompatBlocks.powerConvertor.get().getRegistryName().toString(), new ResourceLocation("buildcraftcompat:block/power_convertor")); + } +} diff --git a/common/buildcraft/compat/module/crafttweaker/AssemblyTable.java b/common/buildcraft/compat/module/crafttweaker/AssemblyTable.java index a06e22c..6383873 100644 --- a/common/buildcraft/compat/module/crafttweaker/AssemblyTable.java +++ b/common/buildcraft/compat/module/crafttweaker/AssemblyTable.java @@ -1,105 +1,224 @@ package buildcraft.compat.module.crafttweaker; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.ImmutableSet.Builder; - -import net.minecraft.item.ItemStack; -import net.minecraft.item.crafting.Ingredient; -import net.minecraft.util.ResourceLocation; - import buildcraft.api.mj.MjAPI; -import buildcraft.api.recipes.AssemblyRecipeBasic; +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.action.recipe.ActionAddRecipe; +import com.blamejared.crafttweaker.api.action.recipe.ActionRemoveRecipeByName; +import com.blamejared.crafttweaker.api.annotation.ZenRegister; +import com.blamejared.crafttweaker.api.ingredient.IIngredient; +import com.blamejared.crafttweaker.api.item.IItemStack; +import com.blamejared.crafttweaker.api.recipe.component.BuiltinRecipeComponents; +import com.blamejared.crafttweaker.api.recipe.component.DecomposedRecipeBuilder; +import com.blamejared.crafttweaker.api.recipe.component.IDecomposedRecipe; +import com.blamejared.crafttweaker.api.recipe.handler.IRecipeHandler; +import com.blamejared.crafttweaker.api.recipe.manager.base.IRecipeManager; +import com.blamejared.crafttweaker.api.util.ItemStackUtil; +import com.blamejared.crafttweaker.api.util.StringUtil; +import com.google.common.collect.ImmutableSet; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.RecipeType; +import org.openzen.zencode.java.ZenCodeGlobals; +import org.openzen.zencode.java.ZenCodeType; + +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +//@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; -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; + private static int ids; -@ZenClass("mods.buildcraft.AssemblyTable") -@ModOnly("buildcraftsilicon") -public class AssemblyTable { +// // @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 int ids; + // @ZenMethod + @ZenCodeType.Method +// public static void addRecipe(String name, IItemStack output, int power, IIngredient[] ingredients) + public void enableFacadeAssembly() { + enableFacadeAssembly0(); + } - @ZenMethod - public static void addRecipe(IItemStack output, int power, IIngredient[] ingredients) { - addRecipe0("auto_" + ids++, output, power, ingredients); + // 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)); } - @ZenMethod - public static 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) + private void enableFacadeAssembly0() { +// CraftTweakerAPI.apply(new AddRecipeAction(name, output, power, ingredients)); + CraftTweakerAPI.apply(AddRecipeAction.createFacadeRecipe(this)); } - 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 removeByName(String name) + public void removeByName(String name) { +// CraftTweakerAPI.apply(new RemoveRecipeByNameAction(new ResourceLocation(name))); + CraftTweakerAPI.apply(new RemoveRecipeByNameAction(this, new ResourceLocation(name))); } - @ZenMethod - public static void removeByName(String name) { - CraftTweakerAPI.apply(new RemoveRecipeByNameAction(new ResourceLocation(name))); + @Override + public RecipeType getRecipeType() { + return IAssemblyRecipe.TYPE; } - // ###################### - // ### Action classes ### - // ###################### + @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);", + StringUtil.quoteAndEscape(recipe.getId()), + ItemStackUtil.getCommandString(recipe.getOutputPreviews().stream().toList().get(0)), + recipe.getRequiredMicroJoules(), + recipe.getRequiredIngredientStacks().stream() + .map(i -> IIngredient.fromIngredient(i.ingredient)) + .map(IIngredient::getCommandString) + .collect(Collectors.joining(", ", "[", "]")) + ); + } + } - private static class AddRecipeAction implements IAction { + @Override + public > boolean doesConflict(IRecipeManager iRecipeManager, IAssemblyRecipe assemblyRecipe, U u) { + if (assemblyRecipe.getClass() == FacadeAssemblyRecipes.class && u.getClass() == FacadeAssemblyRecipes.class) { + return true; + } + return u instanceof IAssemblyRecipe && + ((IAssemblyRecipe) u).getRequiredIngredientStacks().stream() + .allMatch(u_ingredientStack -> + assemblyRecipe.getIngredients().stream() + .anyMatch(r_ingredientStack -> Arrays.stream(r_ingredientStack.getItems()).anyMatch(u_ingredientStack.ingredient::test)) + ); + } - private final ItemStack output; - private final ResourceLocation name; - private final long requiredMj; - private final ImmutableSet requiredStacks; + @Override + public Optional decompose(IRecipeManager iRecipeManager, IAssemblyRecipe assemblyRecipe) { + DecomposedRecipeBuilder builder = IDecomposedRecipe.builder(); + assemblyRecipe.getRequiredIngredientStacks().forEach(ingredientStack -> + builder.with(BCRecipeComponents.INGREDIENT_STACK, ingredientStack) + ); + builder.with(BCRecipeComponents.MJ, assemblyRecipe.getRequiredMicroJoules()); + builder.with(BuiltinRecipeComponents.Output.ITEMS, assemblyRecipe.getOutput().stream().map(IItemStack::of).toList()); + return Optional.of(builder.build()); + } - public AddRecipeAction(String name, IItemStack output, int power, IIngredient[] ingredients) { - this.output = CraftTweakerMC.getItemStack(output); + @Override + public Optional recompose(IRecipeManager iRecipeManager, ResourceLocation id, IDecomposedRecipe iDecomposedRecipe) { + List requiredStacks = iDecomposedRecipe.getOrThrow(BCRecipeComponents.INGREDIENT_STACK); + long requiredMicroJoules = iDecomposedRecipe.getOrThrowSingle(BCRecipeComponents.MJ); + ItemStack output = iDecomposedRecipe.getOrThrowSingle(BuiltinRecipeComponents.Output.ITEMS).getInternal(); + return Optional.of(new AssemblyRecipeBasic(id, requiredMicroJoules, ImmutableSet.copyOf(requiredStacks), output)); + } - 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); + 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, ctIng.asIIngredientWithAmount().getAmount()))); + } + + 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 " + this.recipe.getOutputPreviews().stream().toList().get(0); } } } diff --git a/common/buildcraft/compat/module/crafttweaker/BCRecipeComponents.java b/common/buildcraft/compat/module/crafttweaker/BCRecipeComponents.java new file mode 100644 index 0000000..8709243 --- /dev/null +++ b/common/buildcraft/compat/module/crafttweaker/BCRecipeComponents.java @@ -0,0 +1,49 @@ +package buildcraft.compat.module.crafttweaker; + +import buildcraft.api.BCModules; +import buildcraft.api.recipes.IngredientStack; +import buildcraft.lib.misc.StackUtil; +import com.blamejared.crafttweaker.api.recipe.component.IRecipeComponent; +import com.google.gson.reflect.TypeToken; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; + +import java.util.List; +import java.util.Objects; + +public class BCRecipeComponents { + public static final IRecipeComponent MJ = IRecipeComponent.simple( + ResourceLocation.tryBuild(BCModules.BUILDCRAFT, "mj"), + new TypeToken<>() {}, + Objects::equals + ); + + public static final IRecipeComponent INGREDIENT_STACK = IRecipeComponent.composite( + ResourceLocation.tryBuild(BCModules.BUILDCRAFT, "ingredient_stack"), + new TypeToken<>() {}, + IngredientStack::equals, + List::of, + ingredientStacks -> ingredientStacks.stream().findFirst().orElse(new IngredientStack(Ingredient.EMPTY)) + ); + + public static final IRecipeComponent DEGREES_COOLING_PER_MB = IRecipeComponent.simple( + ResourceLocation.tryBuild(BCModules.BUILDCRAFT, "degrees_cooling_per_mb"), + new TypeToken<>() {}, + Objects::equals + ); + + public static final IRecipeComponent MULTIPLIER = IRecipeComponent.simple( + ResourceLocation.tryBuild(BCModules.BUILDCRAFT, "multiplier"), + new TypeToken<>() {}, + Objects::equals + ); + + public static final IRecipeComponent ITEM_STACK = IRecipeComponent.composite( + ResourceLocation.tryBuild(BCModules.BUILDCRAFT, "item_stack"), + new TypeToken<>() {}, + ItemStack::equals, + List::of, + itemStacks -> itemStacks.stream().findFirst().orElse(StackUtil.EMPTY) + ); +} diff --git a/common/buildcraft/compat/module/crafttweaker/CombustionEngine.java b/common/buildcraft/compat/module/crafttweaker/CombustionEngine.java index f1cb66a..c494ad3 100644 --- a/common/buildcraft/compat/module/crafttweaker/CombustionEngine.java +++ b/common/buildcraft/compat/module/crafttweaker/CombustionEngine.java @@ -1,153 +1,248 @@ 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.misc.FluidUtilBC; +import buildcraft.lib.recipe.fuel.FuelRegistry; +import com.blamejared.crafttweaker.api.CraftTweakerAPI; +import com.blamejared.crafttweaker.api.action.recipe.ActionAddRecipe; +import com.blamejared.crafttweaker.api.annotation.ZenRegister; +import com.blamejared.crafttweaker.api.fluid.CTFluidIngredient; +import com.blamejared.crafttweaker.api.fluid.IFluidStack; +import com.blamejared.crafttweaker.api.recipe.component.BuiltinRecipeComponents; +import com.blamejared.crafttweaker.api.recipe.component.DecomposedRecipeBuilder; +import com.blamejared.crafttweaker.api.recipe.component.IDecomposedRecipe; +import com.blamejared.crafttweaker.api.recipe.handler.IRecipeHandler; +import com.blamejared.crafttweaker.api.recipe.manager.base.IRecipeManager; +import com.blamejared.crafttweaker.api.util.StringUtil; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.level.material.EmptyFluid; +import net.minecraftforge.fluids.FluidStack; +import org.openzen.zencode.java.ZenCodeGlobals; +import org.openzen.zencode.java.ZenCodeType; -import buildcraft.lib.engine.TileEngineBase_BC8; +import java.util.List; +import java.util.Optional; -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 -> r.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 instanceof IFluidCoolant fluidCoolant && fluidCoolant.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 -> r.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 instanceof IFluidCoolant fluidCoolant && fluidCoolant.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." + } + + @Override + public RecipeType getRecipeType() { + return IFuel.TYPE; + } + + @Override + public String dumpToCommandString(final IRecipeManager manager, IFuel recipe) { + if (recipe instanceof IFuelManager.IDirtyFuel dirtyFuel) { + return String.format( + "combustionEngine.addDirtyFuel(%s, %s, %s, %s, %s);", + StringUtil.quoteAndEscape(recipe.getId()), + StringUtil.quoteAndEscape(FluidUtilBC.getRegistryName(recipe.getFluid().getFluid())), + recipe.getPowerPerCycle(), + recipe.getTotalBurningTime(), + StringUtil.quoteAndEscape(FluidUtilBC.getRegistryName(dirtyFuel.getResidue().getFluid())) + ); + } else { + return String.format( + "combustionEngine.addCleanFuel(%s, %s, %s, %s);", + StringUtil.quoteAndEscape(recipe.getId()), + StringUtil.quoteAndEscape(FluidUtilBC.getRegistryName(recipe.getFluid().getFluid())), + recipe.getPowerPerCycle(), + recipe.getTotalBurningTime() ); } - 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) { - // - // } + @Override + public > boolean doesConflict(IRecipeManager iRecipeManager, IFuel fuel, U u) { + return u instanceof IFuel && ((IFuel) u).getFluid().getFluid() == fuel.getFluid().getFluid(); + } - // ###################### - // ### Action classes ### - // ###################### + @Override + public Optional decompose(IRecipeManager iRecipeManager, IFuel fuel) { + DecomposedRecipeBuilder builder = IDecomposedRecipe.builder(); + builder.with(BuiltinRecipeComponents.Input.FLUID_INGREDIENTS, new CTFluidIngredient.FluidStackIngredient(IFluidStack.of(fuel.getFluid()))); + if (fuel instanceof IFuelManager.IDirtyFuel dirtyFuel) { + builder.with(BuiltinRecipeComponents.Output.FLUIDS, IFluidStack.of(dirtyFuel.getResidue())); + } + builder.with(BuiltinRecipeComponents.Processing.TIME, fuel.getTotalBurningTime()); + builder.with(BCRecipeComponents.MJ, fuel.getPowerPerCycle() * fuel.getTotalBurningTime()); + return Optional.of(builder.build()); + } - static final class AddCleanFuel implements IAction { + @Override + public Optional recompose(IRecipeManager iRecipeManager, ResourceLocation id, IDecomposedRecipe iDecomposedRecipe) { + // input oil + CTFluidIngredient inputFluidIngredient = iDecomposedRecipe.getOrThrowSingle(BuiltinRecipeComponents.Input.FLUID_INGREDIENTS); + Optional inputOptional = CompatModuleCraftTweaker.ctFluidIngredient2SingleFluidStack(inputFluidIngredient); + if (inputOptional.isEmpty()) { + return Optional.empty(); + } + // totalBurningTime powerPerCycle + int totalBurningTime = iDecomposedRecipe.getOrThrowSingle(BuiltinRecipeComponents.Processing.TIME); + long mj = iDecomposedRecipe.getOrThrowSingle(BCRecipeComponents.MJ); + long powerPerCycle = mj / totalBurningTime; + // output residue + List outputFluidStacks = iDecomposedRecipe.get(BuiltinRecipeComponents.Output.FLUIDS); + Optional outputOptional = CompatModuleCraftTweaker.iFluidStack2SingleFluidStack(outputFluidStacks); + if (outputOptional.isEmpty()) { + FuelRegistry.Fuel fuel = new FuelRegistry.Fuel(id, inputOptional.get(), powerPerCycle, totalBurningTime); + return Optional.of(fuel); + } else { + FuelRegistry.DirtyFuel dirtyFuel = new FuelRegistry.DirtyFuel(id, inputOptional.get(), powerPerCycle, totalBurningTime, outputOptional.get()); + return Optional.of(dirtyFuel); + } + } - 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 " + 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 " + 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..586d093 100644 --- a/common/buildcraft/compat/module/crafttweaker/CompatModuleCraftTweaker.java +++ b/common/buildcraft/compat/module/crafttweaker/CompatModuleCraftTweaker.java @@ -1,18 +1,38 @@ package buildcraft.compat.module.crafttweaker; import buildcraft.compat.CompatModuleBase; +import com.blamejared.crafttweaker.api.fluid.CTFluidIngredient; +import com.blamejared.crafttweaker.api.fluid.IFluidStack; +import net.minecraftforge.fluids.FluidStack; -import crafttweaker.CraftTweakerAPI; +import java.util.List; +import java.util.Optional; 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); + } + + public static Optional ctFluidIngredient2SingleFluidStack(CTFluidIngredient fluidIngredient) { + List fluidStacks = fluidIngredient.getMatchingStacks(); + return iFluidStack2SingleFluidStack(fluidStacks); + } + + public static Optional iFluidStack2SingleFluidStack(List fluidStacks) { + if (!fluidStacks.isEmpty()) { + IFluidStack ctFluidStack = fluidStacks.get(0); + FluidStack fluidStack = ctFluidStack.getInternal(); + return Optional.of(fluidStack); + } + return Optional.empty(); } } diff --git a/common/buildcraft/compat/module/crafttweaker/Coolant.java b/common/buildcraft/compat/module/crafttweaker/Coolant.java new file mode 100644 index 0000000..6133e68 --- /dev/null +++ b/common/buildcraft/compat/module/crafttweaker/Coolant.java @@ -0,0 +1,185 @@ +package buildcraft.compat.module.crafttweaker; + +import buildcraft.api.fuels.ICoolant; +import buildcraft.api.fuels.IFluidCoolant; +import buildcraft.api.fuels.ISolidCoolant; +import buildcraft.lib.misc.FluidUtilBC; +import buildcraft.lib.recipe.coolant.CoolantRegistry; +import com.blamejared.crafttweaker.api.CraftTweakerAPI; +import com.blamejared.crafttweaker.api.action.recipe.ActionAddRecipe; +import com.blamejared.crafttweaker.api.annotation.ZenRegister; +import com.blamejared.crafttweaker.api.fluid.CTFluidIngredient; +import com.blamejared.crafttweaker.api.fluid.IFluidStack; +import com.blamejared.crafttweaker.api.item.IItemStack; +import com.blamejared.crafttweaker.api.recipe.component.BuiltinRecipeComponents; +import com.blamejared.crafttweaker.api.recipe.component.DecomposedRecipeBuilder; +import com.blamejared.crafttweaker.api.recipe.component.IDecomposedRecipe; +import com.blamejared.crafttweaker.api.recipe.handler.IRecipeHandler; +import com.blamejared.crafttweaker.api.recipe.manager.base.IRecipeManager; +import com.blamejared.crafttweaker.api.util.ItemStackUtil; +import com.blamejared.crafttweaker.api.util.StringUtil; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.level.material.EmptyFluid; +import net.minecraftforge.fluids.FluidStack; +import org.openzen.zencode.java.ZenCodeGlobals; +import org.openzen.zencode.java.ZenCodeType; + +import java.util.Optional; + +@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 instanceof IFluidCoolant fluidCoolant && fluidCoolant.getFluid().equals(fluid))) { + throw new IllegalArgumentException("The fluid " + fluid + " is already registered as a coolant!"); + } else if (CombustionEngine.INSTANCE.getAllRecipes().stream().anyMatch(r -> r.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 instanceof ISolidCoolant solidCoolant && solidCoolant.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 RecipeType getRecipeType() { + return ICoolant.TYPE; + } + + @Override + public String dumpToCommandString(final IRecipeManager manager, ICoolant recipe) { + if (recipe instanceof IFluidCoolant fluidCoolant) { + return String.format( + "coolant.addFluidCoolant(%s, %s, %s);", + StringUtil.quoteAndEscape(recipe.getId()), + StringUtil.quoteAndEscape(FluidUtilBC.getRegistryName(recipe.getFluid().getFluid())), + fluidCoolant.getDegreesCoolingPerMB() + ); + } else if (recipe instanceof ISolidCoolant solidCoolant) { + return String.format( + "coolant.addSolidCoolant(%s, %s, %s, %s);", + StringUtil.quoteAndEscape(recipe.getId()), + ItemStackUtil.getCommandString(solidCoolant.getSolid()), + StringUtil.quoteAndEscape(FluidUtilBC.getRegistryName(recipe.getFluid().getFluid())), + solidCoolant.getMultiplier() + ); + } + return "This is not a fluid coolant or a solid coolant. What happened?"; + } + + @Override + public > boolean doesConflict(IRecipeManager iRecipeManager, ICoolant coolant, U u) { + if (coolant instanceof IFluidCoolant && u instanceof IFluidCoolant) { + return coolant.getFluid().getFluid() == ((IFluidCoolant) u).getFluid().getFluid(); + } else if (coolant instanceof ISolidCoolant && u instanceof ISolidCoolant) { + return ((ISolidCoolant) coolant).getSolid().getItem() == ((ISolidCoolant) u).getSolid().getItem(); + } else { + return false; + } + } + + @Override + public Optional decompose(IRecipeManager iRecipeManager, ICoolant coolant) { + DecomposedRecipeBuilder builder = IDecomposedRecipe.builder(); + if (coolant instanceof IFluidCoolant) { + builder.with(BuiltinRecipeComponents.Input.FLUID_INGREDIENTS, new CTFluidIngredient.FluidStackIngredient(IFluidStack.of(coolant.getFluid()))); + builder.with(BCRecipeComponents.DEGREES_COOLING_PER_MB, ((IFluidCoolant) coolant).getDegreesCoolingPerMB()); + } else if (coolant instanceof ISolidCoolant) { + builder.with(BuiltinRecipeComponents.Input.FLUID_INGREDIENTS, new CTFluidIngredient.FluidStackIngredient(IFluidStack.of(coolant.getFluid()))); + builder.with(BCRecipeComponents.ITEM_STACK, ((ISolidCoolant) coolant).getSolid()); + builder.with(BCRecipeComponents.MULTIPLIER, ((ISolidCoolant) coolant).getMultiplier()); + } else { + return Optional.empty(); + } + return Optional.of(builder.build()); + } + + @Override + public Optional recompose(IRecipeManager iRecipeManager, ResourceLocation id, IDecomposedRecipe iDecomposedRecipe) { + if (!iDecomposedRecipe.get(BCRecipeComponents.DEGREES_COOLING_PER_MB).isEmpty()) { + // IFluidCoolant + Optional fluidOptional = CompatModuleCraftTweaker.ctFluidIngredient2SingleFluidStack(iDecomposedRecipe.getOrThrowSingle(BuiltinRecipeComponents.Input.FLUID_INGREDIENTS)); + if (fluidOptional.isEmpty()) { + return Optional.empty(); + } + FluidStack fluid = fluidOptional.get(); + float degreesCoolingPerMB = iDecomposedRecipe.getOrThrowSingle(BCRecipeComponents.DEGREES_COOLING_PER_MB); + return Optional.of(new CoolantRegistry.FluidCoolant(id, fluid, degreesCoolingPerMB)); + } else if (!iDecomposedRecipe.get(BCRecipeComponents.MULTIPLIER).isEmpty()) { + ItemStack solid = iDecomposedRecipe.getOrThrowSingle(BCRecipeComponents.ITEM_STACK); + FluidStack fluid = iDecomposedRecipe.getOrThrowSingle(BuiltinRecipeComponents.Input.FLUID_INGREDIENTS).getMatchingStacks().get(0).getInternal(); + float multiplier = iDecomposedRecipe.getOrThrowSingle(BCRecipeComponents.MULTIPLIER); + return Optional.of(new CoolantRegistry.SolidCoolant(id, solid, fluid, multiplier)); + } else { + return Optional.empty(); + } + } + + 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 " + 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/forge/BlockPowerConvertor.java b/common/buildcraft/compat/module/forge/BlockPowerConvertor.java new file mode 100644 index 0000000..8e8c32c --- /dev/null +++ b/common/buildcraft/compat/module/forge/BlockPowerConvertor.java @@ -0,0 +1,17 @@ +package buildcraft.compat.module.forge; + +import buildcraft.lib.block.BlockBCTile_Neptune; +import buildcraft.lib.tile.TileBC_Neptune; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.state.BlockState; + +public class BlockPowerConvertor extends BlockBCTile_Neptune { + public BlockPowerConvertor(String idBC, Properties props) { + super(idBC, props); + } + + @Override + public TileBC_Neptune newBlockEntity(BlockPos pos, BlockState state) { + return new TilePowerConvertor(pos, state); + } +} diff --git a/common/buildcraft/compat/module/forge/TilePowerConvertor.java b/common/buildcraft/compat/module/forge/TilePowerConvertor.java new file mode 100644 index 0000000..7aeb1e5 --- /dev/null +++ b/common/buildcraft/compat/module/forge/TilePowerConvertor.java @@ -0,0 +1,276 @@ +package buildcraft.compat.module.forge; + +import buildcraft.api.core.EnumPipePart; +import buildcraft.api.mj.*; +import buildcraft.compat.BCCompatBlocks; +import buildcraft.lib.tile.TileBC_Neptune; +import com.mojang.datafixers.util.Pair; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.ForgeCapabilities; +import net.minecraftforge.energy.IEnergyStorage; + +import javax.annotation.Nonnull; +import java.util.Arrays; +import java.util.List; + +// Calen +public class TilePowerConvertor extends TileBC_Neptune implements IEnergyStorage, IMjConnector, IMjReceiver, IMjRedstoneReceiver, IMjReadable, IMjPassiveProvider { + public TilePowerConvertor(BlockPos pos, BlockState blockState) { + super(BCCompatBlocks.powerConvertorTile.get(), pos, blockState); + caps.addCapabilityInstance(ForgeCapabilities.ENERGY, this, EnumPipePart.VALUES); + caps.addCapabilityInstance(MjAPI.CAP_CONNECTOR, this, EnumPipePart.VALUES); + caps.addCapabilityInstance(MjAPI.CAP_REDSTONE_RECEIVER, this, EnumPipePart.VALUES); + caps.addCapabilityInstance(MjAPI.CAP_READABLE, this, EnumPipePart.VALUES); + caps.addCapabilityInstance(MjAPI.CAP_RECEIVER, this, EnumPipePart.VALUES); + caps.addCapabilityInstance(MjAPI.CAP_PASSIVE_PROVIDER, this, EnumPipePart.VALUES); + } + + // IMjConnector + @Override + public boolean canConnect(@Nonnull IMjConnector other) { + return true; + } + + // IMjPassiveProvider + @Override + public long extractPower(long min, long max, final boolean simulate) { + int min_FE = convert_mMJ_2_FE(min); + int max_FE = convert_mMJ_2_FE(max); + List> toQuery = getAllHasCapAround(ForgeCapabilities.ENERGY); + // try getting power from each IEnergyStorage in toQuery + List>> queried = toQuery.stream().map(p -> { + IEnergyStorage energyStorage = p.getSecond(); + int extractedFE = energyStorage.extractEnergy(max_FE, true); + return new Pair<>(p.getFirst(), new Pair<>(p.getSecond(), extractedFE)); + }) + .filter(p -> p.getSecond().getSecond() > 0) + .toList(); + // get max power can get + int neighbourTotalCanProvide_FE = 0; + for (Pair> p : queried) { + neighbourTotalCanProvide_FE += p.getSecond().getSecond(); + } + if (neighbourTotalCanProvide_FE < min_FE) { + // if cannot support [min], fail + return 0; + } else { + // if can support [min] + final int final_neighbourTotalCanProvide_FE = neighbourTotalCanProvide_FE; + // if can provide more than [max], each provides weighted average value + if (neighbourTotalCanProvide_FE > max_FE) { + queried = queried.stream() + .map(p -> new Pair<>(p.getFirst(), new Pair<>(p.getSecond().getFirst(), p.getSecond().getSecond() * max_FE / final_neighbourTotalCanProvide_FE))) + .toList(); + } + // extract! + int trueExtracted_FE = 0; + for (Pair> p : queried) { + trueExtracted_FE += p.getSecond().getFirst().extractEnergy(p.getSecond().getSecond(), simulate); + } + return convert_FE_2_mMJ(trueExtracted_FE); + } + } + + // IMjReadable + @Override + public long getStored() { + List> toQuery = getAllHasCapAround(ForgeCapabilities.ENERGY); + int stored_FE = 0; + for (Pair p : toQuery) { + stored_FE += p.getSecond().getEnergyStored(); + } + return convert_FE_2_mMJ(stored_FE); + } + + // IMjReadable + @Override + public long getCapacity() { + List> toQuery = getAllHasCapAround(ForgeCapabilities.ENERGY); + int stored_FE = 0; + for (Pair p : toQuery) { + stored_FE += p.getSecond().getMaxEnergyStored(); + } + return convert_FE_2_mMJ(stored_FE); + } + + // IMjReceiver + @Override + public long getPowerRequested() { + List> toQuery = getAllHasCapAround(ForgeCapabilities.ENERGY); + int stored_FE = 0; + for (Pair p : toQuery) { + IEnergyStorage capFE = p.getSecond(); + stored_FE += capFE.canReceive() ? Math.max(capFE.receiveEnergy(Integer.MAX_VALUE, true), 0) : 0; + } + return convert_FE_2_mMJ(stored_FE); + } + + // IMjReceiver + @Override + public long receivePower(long max_mMJ, boolean simulate) { + int max_FE = convert_mMJ_2_FE(max_mMJ); + List> toQuery = getAllHasCapAround(ForgeCapabilities.ENERGY); + // try getting power from each IEnergyStorage in toQuery + List>> queried = toQuery.stream().map(p -> { + IEnergyStorage energyStorage = p.getSecond(); + int receivedFE = energyStorage.receiveEnergy(max_FE, true); + return new Pair<>(p.getFirst(), new Pair<>(p.getSecond(), receivedFE)); + }) + .filter(p -> p.getSecond().getSecond() > 0) + .toList(); + // get max power can receive + int neighbourTotalCanReceive_FE = 0; + for (Pair> p : queried) { + neighbourTotalCanReceive_FE += p.getSecond().getSecond(); + } + // if can provide more than [max], each provides weighted average value + final int final_neighbourTotalCanReceive_FE = neighbourTotalCanReceive_FE; + if (neighbourTotalCanReceive_FE > max_FE) { + queried = queried.stream() + .map(p -> new Pair<>(p.getFirst(), new Pair<>(p.getSecond().getFirst(), p.getSecond().getSecond() * max_FE / final_neighbourTotalCanReceive_FE))) + .toList(); + } + // receive! + int trueReceived_FE = 0; + for (Pair> p : queried) { + trueReceived_FE += p.getSecond().getFirst().receiveEnergy(p.getSecond().getSecond(), simulate); + } + int trueExcess_FE = max_FE - trueReceived_FE; + return convert_FE_2_mMJ(trueExcess_FE); + } + + // IEnergyStorage + // IMjReceiver + @Override + public boolean canReceive() { + return true; + } + + // IEnergyStorage + @Override + public int receiveEnergy(int max_FE, boolean simulate) { + long max_mMJ = convert_FE_2_mMJ(max_FE); + List> toQuery = getAllHasCapAround(MjAPI.CAP_RECEIVER); + // try getting power from each IMjReceiver in toQuery + List>> queried = toQuery.stream().map(p -> { + IMjReceiver mjReceiver = p.getSecond(); + long excess_FE = mjReceiver.receivePower(max_mMJ, true); + long received_FE = max_mMJ - excess_FE; + return new Pair<>(p.getFirst(), new Pair<>(p.getSecond(), received_FE)); + }) + .filter(p -> p.getSecond().getSecond() > 0) + .toList(); + // get max power can receive + long neighbourTotalCanReceive_FE = 0; + for (Pair> p : queried) { + neighbourTotalCanReceive_FE += p.getSecond().getSecond(); + } + // if can provide more than [max], each provides weighted average value + final long final_neighbourTotalCanReceive_FE = neighbourTotalCanReceive_FE; + if (neighbourTotalCanReceive_FE > max_mMJ) { + queried = queried.stream() + .map(p -> new Pair<>(p.getFirst(), new Pair<>(p.getSecond().getFirst(), p.getSecond().getSecond() * max_mMJ / final_neighbourTotalCanReceive_FE))) + .toList(); + } + // receive! + long trueExcess_FE = 0; + for (Pair> p : queried) { + trueExcess_FE += p.getSecond().getFirst().receivePower(p.getSecond().getSecond(), simulate); + } + long trueReceived_FE = max_FE - trueExcess_FE; + return convert_mMJ_2_FE(trueReceived_FE); + } + + @Override + public int extractEnergy(int max_FE, boolean simulate) { + long max_mMJ = convert_FE_2_mMJ(max_FE); + List> toQuery = getAllHasCapAround(MjAPI.CAP_PASSIVE_PROVIDER); + // try getting power from each IEnergyStorage in toQuery + List>> queried = toQuery.stream().map(p -> { + IMjPassiveProvider energyStorage = p.getSecond(); + long extractedFE = energyStorage.extractPower(0, max_mMJ, true); + return new Pair<>(p.getFirst(), new Pair<>(p.getSecond(), extractedFE)); + }) + .filter(p -> p.getSecond().getSecond() > 0) + .toList(); + // get max power can get + long neighbourTotalCanProvide_mMJ = 0; + for (Pair> p : queried) { + neighbourTotalCanProvide_mMJ += p.getSecond().getSecond(); + } + // if can provide more than [max], each provides weighted average value + final long final_neighbourTotalCanProvide_FE = neighbourTotalCanProvide_mMJ; + if (neighbourTotalCanProvide_mMJ > max_mMJ) { + queried = queried.stream() + .map(p -> new Pair<>(p.getFirst(), new Pair<>(p.getSecond().getFirst(), p.getSecond().getSecond() * max_mMJ / final_neighbourTotalCanProvide_FE))) + .toList(); + } + // extract! + long trueExtracted_mMJ = 0; + for (Pair> p : queried) { + trueExtracted_mMJ += p.getSecond().getFirst().extractPower(0, p.getSecond().getSecond(), simulate); + } + return convert_mMJ_2_FE(trueExtracted_mMJ); + } + + @Override + public int getEnergyStored() { + List> toQuery = getAllHasCapAround(MjAPI.CAP_READABLE); + long neighbourTotalEnergyStored_mMJ = 0; + for (Pair p : toQuery) { + neighbourTotalEnergyStored_mMJ += p.getSecond().getStored(); + } + return convert_mMJ_2_FE(neighbourTotalEnergyStored_mMJ); + } + + @Override + public int getMaxEnergyStored() { + List> toQuery = getAllHasCapAround(MjAPI.CAP_READABLE); + long neighbourTotalMaxEnergyStored_mMJ = 0; + for (Pair p : toQuery) { + neighbourTotalMaxEnergyStored_mMJ += p.getSecond().getCapacity(); + } + return convert_mMJ_2_FE(neighbourTotalMaxEnergyStored_mMJ); + } + + @Override + public boolean canExtract() { + return true; + } + + /** + * To get all capability instances of capability provider TileEntities all around this. + * {@link TilePowerConvertor} and any TileEntity both has {@link ForgeCapabilities#ENERGY} and {@link MjAPI#CAP_CONNECTOR} will be excluded. + */ + private List> getAllHasCapAround(Capability capability) { + return Arrays.stream(Direction.values()) + .map(d -> new Pair<>(d, this.worldPosition.relative(d))) + .filter(p -> this.level.getBlockState(p.getSecond()).getBlock() != BCCompatBlocks.powerConvertor.get()) + .map(p -> new Pair<>(p.getFirst(), this.level.getBlockEntity(p.getSecond()))) + .filter(p -> p.getSecond() != null) + // should not have both + .filter(p -> { + Direction dir = p.getFirst(); + BlockEntity te = p.getSecond(); + boolean has_FORGE_ENERGY = te.getCapability(ForgeCapabilities.ENERGY, dir).isPresent(); + boolean has_CAP_CONNECTOR = te.getCapability(MjAPI.CAP_CONNECTOR, dir).isPresent(); + return !(has_FORGE_ENERGY && has_CAP_CONNECTOR); + }) + .map(p -> new Pair<>(p.getFirst(), p.getSecond().getCapability(capability, p.getFirst().getOpposite()))) + .filter(p -> p.getSecond().isPresent()) + .map(p -> new Pair<>(p.getFirst(), p.getSecond().orElse(null))) + .toList(); + } + + public static int convert_mMJ_2_FE(long mMJ) { + return (int) Math.min(Integer.MAX_VALUE, mMJ / MjAPI.MJ * 16L); + } + + public static long convert_FE_2_mMJ(int fe) { + return fe * MjAPI.MJ / 16L; + } +} diff --git a/common/buildcraft/compat/module/ic2/CompatModuleIndustrialCraft2.java b/common/buildcraft/compat/module/ic2/CompatModuleIndustrialCraft2.java index 01c782d..bd441c6 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.resources.ResourceLocation; +import net.minecraft.world.item.Item; +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..74ad674 100644 --- a/common/buildcraft/compat/module/jei/BCPluginJEI.java +++ b/common/buildcraft/compat/module/jei/BCPluginJEI.java @@ -1,150 +1,234 @@ 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.BCLibItems; +import buildcraft.lib.gui.GuiBC8; +import buildcraft.lib.item.ItemGuide; +import buildcraft.lib.misc.ColourUtil; +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.BCSiliconItems; +import buildcraft.silicon.BCSiliconMenuTypes; import buildcraft.silicon.container.ContainerAssemblyTable; - -import mezz.jei.api.IGuiHelper; +import buildcraft.transport.BCTransportItems; +import buildcraft.transport.pipe.PipeRegistry; +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.RecipeTypes; +import mezz.jei.api.constants.VanillaTypes; +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.resources.ResourceLocation; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.fml.ModList; + +import java.util.Arrays; +import java.util.List; -@JEIPlugin +@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(CategoryCoolable.RECIPE_TYPE, ImmutableList.copyOf(Minecraft.getInstance().level.getRecipeManager().getAllRecipesFor(IRefineryRecipeManager.ICoolableRecipe.TYPE))); +// registry.addRecipes(ImmutableList.copyOf(BuildcraftRecipeRegistry.refineryRecipes.getDistillationRegistry().getAllRecipes()), new ResourceLocation("buildcraft:category_distiller")); + registry.addRecipes(CategoryDistiller.RECIPE_TYPE, ImmutableList.copyOf(Minecraft.getInstance().level.getRecipeManager().getAllRecipesFor(IRefineryRecipeManager.IDistillationRecipe.TYPE))); +// registry.addRecipes(ImmutableList.copyOf(BuildcraftRecipeRegistry.refineryRecipes.getHeatableRegistry().getAllRecipes()), new ResourceLocation("buildcraft:category_heatable")); + registry.addRecipes(CategoryHeatable.RECIPE_TYPE, ImmutableList.copyOf(Minecraft.getInstance().level.getRecipeManager().getAllRecipesFor(IRefineryRecipeManager.IHeatableRecipe.TYPE))); } + 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(CategoryCombustionEngine.RECIPE_TYPE, ImmutableList.copyOf(Minecraft.getInstance().level.getRecipeManager().getAllRecipesFor(IFuel.TYPE))); } - 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(CategoryAssemblyTable.RECIPE_TYPE, ImmutableList.copyOf(Minecraft.getInstance().level.getRecipeManager().getAllRecipesFor(AssemblyRecipe.TYPE))); } + } - 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(), RecipeTypes.CRAFTING); +// registry.addRecipeTransferHandler(new AdvancedCraftingItemsTransferHandler(), "minecraft.crafting"); + registry.addRecipeTransferHandler(new AdvancedCraftingItemsTransferHandler(), RecipeTypes.CRAFTING); +// registry.addRecipeTransferHandler(ContainerAssemblyTable.class, "buildcraft-compat:silicon.assembly", 36, 12, 0, 36); + registry.addRecipeTransferHandler(ContainerAssemblyTable.class, BCSiliconMenuTypes.ASSEMBLY_TABLE, CategoryAssemblyTable.RECIPE_TYPE, 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.RECIPE_TYPE); + } + + if (BCFactoryBlocks.heatExchange != null) { +// registry.addRecipeCatalyst(new ItemStack(BCFactoryBlocks.heatExchange.get()), new String[]{"buildcraft:category_coolable"}); + registry.addRecipeCatalyst(new ItemStack(BCFactoryBlocks.heatExchange.get()), CategoryCoolable.RECIPE_TYPE); +// registry.addRecipeCatalyst(new ItemStack(BCFactoryBlocks.heatExchange.get()), new String[]{"buildcraft:category_heatable"}); + registry.addRecipeCatalyst(new ItemStack(BCFactoryBlocks.heatExchange.get()), CategoryHeatable.RECIPE_TYPE); + } + + if (BCFactoryBlocks.autoWorkbenchItems != null) { + registry.addRecipeCatalyst(new ItemStack(BCFactoryBlocks.autoWorkbenchItems.get()), RecipeTypes.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()), RecipeTypes.FUELING); + } + +// 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.RECIPE_TYPE); + } + } + } + + 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.RECIPE_TYPE); + } + + if (BCSiliconBlocks.advancedCraftingTable != null) { +// registry.addRecipeCatalyst(new ItemStack(BCSiliconBlocks.advancedCraftingTable.get()), new String[]{"minecraft.crafting"}); + registry.addRecipeCatalyst(new ItemStack(BCSiliconBlocks.advancedCraftingTable.get()), RecipeTypes.CRAFTING); + } + } + } + + @Override + public void registerItemSubtypes(ISubtypeRegistration registration) { + boolean transport = BCModules.TRANSPORT.isLoaded(); + boolean silicon = BCModules.SILICON.isLoaded(); + if (transport) { + registration.registerSubtypeInterpreter(BCTransportItems.wire.get(), (stack, context) -> ColourUtil.getStackColourFromTag(stack).getName()); + } + if (silicon) { + registration.registerSubtypeInterpreter(BCSiliconItems.plugLens.get(), (stack, context) -> String.valueOf(stack.getDamageValue())); + } + registration.registerSubtypeInterpreter(BCLibItems.guide.get(), (stack, context) -> ItemGuide.getBookName(stack)); + } + + @Override + public void onRuntimeAvailable(IJeiRuntime jeiRuntime) { + BCPluginJEI.jeiRuntime = jeiRuntime; + + // TODO if disable colored pipes + Arrays.stream(DyeColor.values()).forEach( + color -> PipeRegistry.INSTANCE.getAllRegisteredPipes().forEach( + def -> jeiRuntime.getIngredientManager().removeIngredientsAtRuntime( + VanillaTypes.ITEM_STACK, + List.of(new ItemStack((Item) PipeRegistry.INSTANCE.getItemForPipe(def, color))) + ) + ) + ); + } } diff --git a/common/buildcraft/compat/module/jei/energy/combustionengine/CategoryCombustionEngine.java b/common/buildcraft/compat/module/jei/energy/combustionengine/CategoryCombustionEngine.java index 323ec89..5f33f6d 100644 --- a/common/buildcraft/compat/module/jei/energy/combustionengine/CategoryCombustionEngine.java +++ b/common/buildcraft/compat/module/jei/energy/combustionengine/CategoryCombustionEngine.java @@ -1,40 +1,88 @@ 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 mezz.jei.api.gui.IRecipeLayout; -import mezz.jei.api.ingredients.IIngredients; -import mezz.jei.api.recipe.BlankRecipeCategory; +import buildcraft.api.fuels.IFuel; +import buildcraft.api.fuels.IFuelManager; +import buildcraft.api.mj.MjAPI; +import buildcraft.energy.BCEnergyBlocks; +import com.google.common.collect.Lists; +import com.mojang.blaze3d.platform.InputConstants; +import com.mojang.blaze3d.vertex.PoseStack; +import mezz.jei.api.constants.VanillaTypes; +import mezz.jei.api.forge.ForgeTypes; +import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; +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.IRecipeSlotsView; +import mezz.jei.api.helpers.IGuiHelper; +import mezz.jei.api.recipe.IFocusGroup; +import mezz.jei.api.recipe.RecipeIngredientRole; +import mezz.jei.api.recipe.RecipeType; +import mezz.jei.api.recipe.category.IRecipeCategory; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +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 { + // Calen + public static final RecipeType RECIPE_TYPE = + RecipeType.create(BCModules.ENERGY.getModId(), "engine_combustion", IFuel.class); + // 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 Font 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(VanillaTypes.ITEM_STACK, 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() { - return UID; + public RecipeType getRecipeType() { + return RECIPE_TYPE; } @Override - public String getTitle() { - return "Combustion Engine Fuels"; + public Component getTitle() { +// return new TextComponent("Combustion Engine Fuels"); + return Component.translatable("buildcraft.jei.title.combustion_engine_fuels"); } - @Override public String getModName() { return BCModules.ENERGY.name(); } @@ -45,27 +93,67 @@ 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)); + // Calen + private int lastBurnTime = -1; - if (recipeWrapper instanceof WrapperCombustionEngine.Dirty) { -// WrapperCombustionEngine.Dirty dirty = (WrapperCombustionEngine.Dirty)recipeWrapper; + @Override + public void draw(IFuel fuel, IRecipeSlotsView recipeSlotsView, GuiGraphics guiGraphics, double mouseX, double mouseY) { + PoseStack poseStack = guiGraphics.pose(); +// this.flame.draw(stack, 2, 0); + this.burnTimeDrabableMap.get(fuel.getTotalBurningTime()).draw(guiGraphics, 2, 0); +// GlStateManager.func_179094_E(); + poseStack.pushPose(); + // Calen: 8->6 +// GlStateManager.func_179109_b(24.0F, 8.0F, 0.0F); +// stack.translate(24.0F, 8.0F, 0.0F); + poseStack.translate(24.0F, 6.0F, 0.0F); +// this.font.draw(stack, "Burns for " + fuel.getTotalBurningTime() / 20 + "s", 0, 0, Color.darkGray.getRGB()); + guiGraphics.drawString(this.font, Component.translatable("buildcraft.jei.title.combustion_engine_fuels.burn_time", fuel.getTotalBurningTime() / 20).getString(), 0, 0, Color.darkGray.getRGB(), false); +// this.font.draw(stack, " at " + MjAPI.formatMj(fuel.getPowerPerCycle()) + " MJ/t", 0, font.lineHeight, Color.darkGray.getRGB()); + guiGraphics.drawString(this.font, Component.translatable("buildcraft.jei.title.combustion_engine_fuels.burn_speed", MjAPI.formatMj(fuel.getPowerPerCycle())).getString(), 0, font.lineHeight, Color.darkGray.getRGB(), false); +// GlStateManager.func_179109_b(0.0F, (float)(minecraft.field_71466_p.field_78288_b * 2), 0.0F); + poseStack.translate(0.0F, (float) (font.lineHeight * 2), 0.0F); +// GlStateManager.func_179139_a(0.7, 0.7, 1.0); + poseStack.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()); + guiGraphics.drawString(this.font, Component.translatable("buildcraft.jei.title.combustion_engine_fuels.burn_total", MjAPI.formatMj(fuel.getPowerPerCycle() * (long) fuel.getTotalBurningTime())).getString(), 1, 2, Color.gray.getRGB(), false); +// GlStateManager.func_179121_F(); + poseStack.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(IRecipeLayoutBuilder builder, IFuel fuel, IFocusGroup focuses) { +// IGuiFluidStackGroup guiFluidStacks = recipeLayout.getFluidStacks(); +// guiFluidStacks.init(0, true, 1, 15, 16, 16, 1000, false, (IDrawable) null); +// guiFluidStacks.set(0, (List) ingredients.getInputs(FluidStack.class).get(0)); + builder + .addSlot(RecipeIngredientRole.INPUT, 1, 15) + .setFluidRenderer(1000, false, 16, 16) + .addIngredient(ForgeTypes.FLUID_STACK, new FluidStack(fuel.getFluid(), 1000)); + if (fuel instanceof IFuelManager.IDirtyFuel dirtyFuel) { + // Calen: move right 20 to not covered the text +// guiFluidStacks.init(1, false, 95, 15, 16, 16, 1000, false, (IDrawable) null); +// guiFluidStacks.set(1, (List) ingredients.getOutputs(FluidStack.class).get(0)); + builder +// .addSlot(RecipeIngredientRole.OUTPUT, 95, 15) + .addSlot(RecipeIngredientRole.OUTPUT, 115, 15) + .setFluidRenderer(1000, false, 16, 16) + .addIngredient(ForgeTypes.FLUID_STACK, 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, IRecipeSlotsView recipeSlotsView, double mouseX, double mouseY) { + return Lists.newArrayList(); + } + + @Override + public boolean handleInput(IFuel recipe, double mouseX, double mouseY, InputConstants.Key input) { + 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..3d25469 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 javax.annotation.ParametersAreNonnullByDefault; -import mcp.MethodsReturnNonnullByDefault; +import net.minecraft.MethodsReturnNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; \ No newline at end of file diff --git a/common/buildcraft/compat/module/jei/factory/CategoryCoolable.java b/common/buildcraft/compat/module/jei/factory/CategoryCoolable.java index 426d952..f913467 100644 --- a/common/buildcraft/compat/module/jei/factory/CategoryCoolable.java +++ b/common/buildcraft/compat/module/jei/factory/CategoryCoolable.java @@ -1,64 +1,131 @@ 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 mezz.jei.api.gui.IRecipeLayout; -import mezz.jei.api.ingredients.IIngredients; -import mezz.jei.api.recipe.BlankRecipeCategory; - -public class CategoryCoolable extends BlankRecipeCategory { - public static final String UID = "buildcraft:category_coolable"; +import buildcraft.api.recipes.IRefineryRecipeManager; +import buildcraft.factory.BCFactoryBlocks; +import com.google.common.collect.Lists; +import com.mojang.blaze3d.platform.InputConstants; +import mezz.jei.api.constants.VanillaTypes; +import mezz.jei.api.forge.ForgeTypes; +import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; +import mezz.jei.api.gui.builder.IRecipeSlotBuilder; +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.IRecipeSlotsView; +import mezz.jei.api.helpers.IGuiHelper; +import mezz.jei.api.recipe.IFocusGroup; +import mezz.jei.api.recipe.RecipeIngredientRole; +import mezz.jei.api.recipe.RecipeType; +import mezz.jei.api.recipe.category.IRecipeCategory; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; + +import java.util.List; + +//public class CategoryCoolable extends BlankRecipeCategory +public class CategoryCoolable implements IRecipeCategory { + // Calen + public static final RecipeType RECIPE_TYPE = + RecipeType.create(BCModules.FACTORY.getModId(), "category_coolable", IRefineryRecipeManager.ICoolableRecipe.class); + 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 IDrawable background, slot; + private final IDrawableAnimated animatedCooling; + private final IDrawableAnimated animatedHeating; - 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); + 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); + + this.icon = guiHelper.createDrawableIngredient(VanillaTypes.ITEM_STACK, new ItemStack(BCFactoryBlocks.heatExchange.get())); + + 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() { - return UID; + public RecipeType getRecipeType() { + return RECIPE_TYPE; } - @Override - public String getTitle() { - return "Coolable Fluids"; + public Component getTitle() { +// return new TextComponent("Coolable Fluids"); + return Component.translatable("buildcraft.jei.title.coolable_fluids"); } - @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) { - IGuiFluidStackGroup guiFluidStacks = recipeLayout.getFluidStacks(); +// public void drawExtras(Minecraft minecraft) + public void draw(IRefineryRecipeManager.ICoolableRecipe recipe, IRecipeSlotsView recipeSlotsView, GuiGraphics guiGraphics, 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(guiGraphics, 0, 1); +// this.slot.draw(stack, 72, 0); + this.slot.draw(guiGraphics, 72, 1); + + // Calen: top padding add 2 to be same height as heatable +// this.animatedCooling.draw(stack, 18, 0); + this.animatedCooling.draw(guiGraphics, 18, 2); +// this.animatedHeating.draw(stack, 18, 0); + this.animatedHeating.draw(guiGraphics, 18, 2); + } - guiFluidStacks.init(0, true, 1, 1, 16, 16, 10, false, null); - guiFluidStacks.set(0, ingredients.getInputs(FluidStack.class).get(0)); + @Override +// public void setRecipe(IRecipeLayout recipeLayout, WrapperCoolable recipeWrapper, IIngredients ingredients) + public void setRecipe(IRecipeLayoutBuilder builder, IRefineryRecipeManager.ICoolableRecipe recipe, IFocusGroup focuses) { +// IGuiFluidStackGroup guiFluidStacks = recipeLayout.getFluidStacks(); +// guiFluidStacks.init(0, true, 1, 1, 16, 16, 10, false, (IDrawable) null); +// guiFluidStacks.set(0, (List) ingredients.getInputs(FluidStack.class).get(0)); + builder +// .addSlot(RecipeIngredientRole.INPUT, 1, 1) + .addSlot(RecipeIngredientRole.INPUT, 1, 2) + .setFluidRenderer(10, false, 16, 16) + .addIngredient(ForgeTypes.FLUID_STACK, recipe.in()); +// guiFluidStacks.init(1, false, 73, 1, 16, 16, 10, false, (IDrawable) null); +// guiFluidStacks.set(1, (List) ingredients.getOutputs(FluidStack.class).get(0)); + IRecipeSlotBuilder slotBuilder = builder +// .addSlot(RecipeIngredientRole.OUTPUT, 73, 1) + .addSlot(RecipeIngredientRole.OUTPUT, 73, 2) + .setFluidRenderer(10, false, 16, 16); + FluidStack out = recipe.out(); + if (out != null && !out.isEmpty()) { + slotBuilder.addIngredient(ForgeTypes.FLUID_STACK, recipe.out()); + } + } - guiFluidStacks.init(1, false, 73, 1, 16, 16, 10, false, null); - guiFluidStacks.set(1, ingredients.getOutputs(FluidStack.class).get(0)); + @Override + public List getTooltipStrings(IRefineryRecipeManager.ICoolableRecipe recipe, IRecipeSlotsView recipeSlotsView, double mouseX, double mouseY) { + return Lists.newArrayList(); + } + + @Override + public boolean handleInput(IRefineryRecipeManager.ICoolableRecipe recipe, double mouseX, double mouseY, InputConstants.Key input) { + return false; } } diff --git a/common/buildcraft/compat/module/jei/factory/CategoryDistiller.java b/common/buildcraft/compat/module/jei/factory/CategoryDistiller.java index 64f4501..04bbc96 100644 --- a/common/buildcraft/compat/module/jei/factory/CategoryDistiller.java +++ b/common/buildcraft/compat/module/jei/factory/CategoryDistiller.java @@ -1,70 +1,133 @@ 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 mezz.jei.api.gui.IRecipeLayout; -import mezz.jei.api.ingredients.IIngredients; -import mezz.jei.api.recipe.BlankRecipeCategory; - -public class CategoryDistiller extends BlankRecipeCategory { - public static final String UID = "buildcraft:category_distiller"; +import buildcraft.api.mj.MjAPI; +import buildcraft.api.recipes.IRefineryRecipeManager; +import buildcraft.factory.BCFactoryBlocks; +import com.google.common.collect.Lists; +import com.mojang.blaze3d.platform.InputConstants; +import mezz.jei.api.constants.VanillaTypes; +import mezz.jei.api.forge.ForgeTypes; +import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; +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.IRecipeSlotsView; +import mezz.jei.api.helpers.IGuiHelper; +import mezz.jei.api.recipe.IFocusGroup; +import mezz.jei.api.recipe.RecipeIngredientRole; +import mezz.jei.api.recipe.RecipeType; +import mezz.jei.api.recipe.category.IRecipeCategory; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +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 class CategoryDistiller implements IRecipeCategory { + // Calen + public static final RecipeType RECIPE_TYPE = + RecipeType.create(BCModules.FACTORY.getModId(), "category_distiller", IRefineryRecipeManager.IDistillationRecipe.class); + 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 Font 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(VanillaTypes.ITEM_STACK, 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() { - return UID; + public RecipeType getRecipeType() { + return RECIPE_TYPE; } @Override - public String getTitle() { - return "Distillable Fluids"; + public Component getTitle() { +// return new TextComponent("Distillable Fluids"); + return Component.translatable("buildcraft.jei.title.distillable_fluids"); } - @Override 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 setRecipe(IRecipeLayout recipeLayout, WrapperDistiller recipeWrapper, IIngredients ingredients) { - IGuiFluidStackGroup guiFluidStacks = recipeLayout.getFluidStacks(); +// public void drawExtras(Minecraft minecraft) + public void draw(IRefineryRecipeManager.IDistillationRecipe recipe, IRecipeSlotsView recipeSlotsView, GuiGraphics guiGraphics, double mouseX, double mouseY) { + this.background.draw(guiGraphics, 20, 4); + this.slot.draw(guiGraphics, 0, 25); + this.slot.draw(guiGraphics, 56, 0); + this.slot.draw(guiGraphics, 56, 45); + + this.animated.draw(guiGraphics, 20, 4); + guiGraphics.drawString(this.font, 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(IRecipeLayoutBuilder builder, IRefineryRecipeManager.IDistillationRecipe recipe, IFocusGroup focuses) { +// 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)); + builder + .addSlot(RecipeIngredientRole.INPUT, 1, 26) + .setFluidRenderer(10, false, 16, 16) + .addIngredient(ForgeTypes.FLUID_STACK, recipe.in()); +// guiFluidStacks.init(1, false, 57, 1, 16, 16, 10, false, (IDrawable) null); +// guiFluidStacks.set(1, (List) ingredients.getOutputs(FluidStack.class).get(0)); + builder + .addSlot(RecipeIngredientRole.OUTPUT, 57, 1) + .setFluidRenderer(10, false, 16, 16) + .addIngredient(ForgeTypes.FLUID_STACK, recipe.outGas()); +// guiFluidStacks.init(2, false, 57, 46, 16, 16, 10, false, (IDrawable) null); +// guiFluidStacks.set(2, (List) ingredients.getOutputs(FluidStack.class).get(1)); + builder + .addSlot(RecipeIngredientRole.OUTPUT, 57, 46) + .setFluidRenderer(10, false, 16, 16) + .addIngredient(ForgeTypes.FLUID_STACK, 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(IRefineryRecipeManager.IDistillationRecipe recipe, IRecipeSlotsView recipeSlotsView, 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 handleInput(IRefineryRecipeManager.IDistillationRecipe recipe, double mouseX, double mouseY, InputConstants.Key input) { + return false; } } diff --git a/common/buildcraft/compat/module/jei/factory/CategoryHeatable.java b/common/buildcraft/compat/module/jei/factory/CategoryHeatable.java index 75300fb..f26ccf0 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 mezz.jei.api.gui.IRecipeLayout; -import mezz.jei.api.ingredients.IIngredients; -import mezz.jei.api.recipe.BlankRecipeCategory; - -public class CategoryHeatable extends BlankRecipeCategory { - public static final String UID = "buildcraft:category_heatable"; +import buildcraft.api.recipes.IRefineryRecipeManager; +import buildcraft.factory.BCFactoryBlocks; +import com.google.common.collect.Lists; +import com.mojang.blaze3d.platform.InputConstants; +import mezz.jei.api.constants.VanillaTypes; +import mezz.jei.api.forge.ForgeTypes; +import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; +import mezz.jei.api.gui.builder.IRecipeSlotBuilder; +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.IRecipeSlotsView; +import mezz.jei.api.helpers.IGuiHelper; +import mezz.jei.api.recipe.IFocusGroup; +import mezz.jei.api.recipe.RecipeIngredientRole; +import mezz.jei.api.recipe.RecipeType; +import mezz.jei.api.recipe.category.IRecipeCategory; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fluids.FluidStack; + +import java.util.List; + +//public class CategoryHeatable extends BlankRecipeCategory +public class CategoryHeatable implements IRecipeCategory { + // Calen + public static final RecipeType RECIPE_TYPE = + RecipeType.create(BCModules.FACTORY.getModId(), "category_heatable", IRefineryRecipeManager.IHeatableRecipe.class); + 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 background, slotIn, slotOut; + private final IDrawable icon; - 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); + private final IDrawableAnimated animated; + + 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(); + + this.icon = guiHelper.createDrawableIngredient(VanillaTypes.ITEM_STACK, 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() { - return UID; + public RecipeType getRecipeType() { + return RECIPE_TYPE; } @Override - public String getTitle() { - return "Heatable Fluids"; + public Component getTitle() { +// return new TextComponent("Heatable Fluids"); + return Component.translatable("buildcraft.jei.title.heatable_fluids"); } - @Override public String getModName() { return BCModules.FACTORY.name(); } @@ -44,22 +81,50 @@ 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) {} + @OnlyIn(Dist.CLIENT) + @Override +// public void drawExtras(Minecraft minecraft) + public void draw(IRefineryRecipeManager.IHeatableRecipe recipe, IRecipeSlotsView recipeSlotsView, GuiGraphics guiGraphics, double mouseX, double mouseY) { + this.slotIn.draw(guiGraphics); + this.slotOut.draw(guiGraphics); + + this.animated.draw(guiGraphics, 18, 0); + } @Override - public void setRecipe(IRecipeLayout recipeLayout, WrapperHeatable recipeWrapper, IIngredients ingredients) { - IGuiFluidStackGroup guiFluidStacks = recipeLayout.getFluidStacks(); +// public void setRecipe(IRecipeLayout recipeLayout, WrapperHeatable recipeWrapper, IIngredients ingredients) + public void setRecipe(IRecipeLayoutBuilder builder, IRefineryRecipeManager.IHeatableRecipe recipe, IFocusGroup focuses) { +// IGuiFluidStackGroup guiFluidStacks = recipeLayout.getFluidStacks(); +// guiFluidStacks.init(0, true, 1, 1, 16, 16, 10, false, (IDrawable) null); +// guiFluidStacks.set(0, (List) ingredients.getInputs(FluidStack.class).get(0)); + builder +// .addSlot(RecipeIngredientRole.INPUT, 1, 1) + .addSlot(RecipeIngredientRole.INPUT, 1, 2) + .setFluidRenderer(10, false, 16, 16) + .addIngredient(ForgeTypes.FLUID_STACK, recipe.in()); +// guiFluidStacks.init(1, false, 73, 1, 16, 16, 10, false, (IDrawable) null); +// guiFluidStacks.set(1, (List) ingredients.getOutputs(FluidStack.class).get(0)); + IRecipeSlotBuilder slotBuilder = builder +// .addSlot(RecipeIngredientRole.OUTPUT, 73, 1) + .addSlot(RecipeIngredientRole.OUTPUT, 73, 2) + .setFluidRenderer(10, false, 16, 16); + FluidStack out = recipe.out(); + if (out != null && !out.isEmpty()) { + slotBuilder.addIngredient(ForgeTypes.FLUID_STACK, 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(IRefineryRecipeManager.IHeatableRecipe recipe, IRecipeSlotsView recipeSlotsView, 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 handleInput(IRefineryRecipeManager.IHeatableRecipe recipe, double mouseX, double mouseY, InputConstants.Key input) { + 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..3153dd2 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 javax.annotation.ParametersAreNonnullByDefault; -import mcp.MethodsReturnNonnullByDefault; +import net.minecraft.MethodsReturnNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; \ No newline at end of file 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..8cf0f13 --- /dev/null +++ b/common/buildcraft/compat/module/jei/gui/GuiHandlerBuildCraft.java @@ -0,0 +1,48 @@ +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.Rect2i; +import net.minecraft.util.Mth; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +public class GuiHandlerBuildCraft implements IGuiContainerHandler> { + @NotNull + @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 endX = Mth.ceil(rect.getEndX()); +// int endY = MathHelper.ceil(rect.getEndY()); + int endY = Mth.ceil(rect.getEndY()); + int width = endX - x; + int height = endY - y; + list.add(new Rect2i(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..15da8e8 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 buildcraft.api.BCModules; +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 mezz.jei.api.constants.VanillaTypes; +import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; +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.IRecipeSlotsView; +import mezz.jei.api.helpers.IGuiHelper; +import mezz.jei.api.recipe.IFocusGroup; +import mezz.jei.api.recipe.RecipeIngredientRole; +import mezz.jei.api.recipe.RecipeType; +import mezz.jei.api.recipe.category.IRecipeCategory; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +import java.awt.*; import java.util.List; +import java.util.*; + +public class CategoryAssemblyTable implements IRecipeCategory { + // Calen + public static final RecipeType RECIPE_TYPE = + RecipeType.create(BCModules.SILICON.getModId(), "assembly", IAssemblyRecipe.class); + // 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; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; + private final IDrawable icon; -import buildcraft.api.BCModules; + private final Map progressBarMap = new HashMap<>(); + private final Map> inputsMap = new HashMap<>(); + private final Map outputsMap = new HashMap<>(); -import mezz.jei.api.IGuiHelper; -import mezz.jei.api.gui.IDrawable; -import mezz.jei.api.gui.IGuiItemStackGroup; -import mezz.jei.api.gui.IRecipeLayout; -import mezz.jei.api.ingredients.IIngredients; -import mezz.jei.api.recipe.IRecipeCategory; + @OnlyIn(Dist.CLIENT) + private Font font = Minecraft.getInstance().font; -public class CategoryAssemblyTable implements IRecipeCategory { - public static final String UID = "buildcraft-compat:silicon.assembly"; + // 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(); - protected final ResourceLocation backgroundLocation; - private final IDrawable background; + this.icon = guiHelper.createDrawableIngredient(VanillaTypes.ITEM_STACK, 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())); + } - 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); + 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() { - return UID; + public RecipeType getRecipeType() { + return RECIPE_TYPE; } @Override - public String getTitle() { - return "Assembly Table"; + public Component getTitle() { +// return new TextComponent("Assembly Table"); + return Component.translatable("tile.assemblyTableBlock.name"); } - @Override public String getModName() { return BCModules.SILICON.name(); } @Override public IDrawable getBackground() { - return background; + return this.background; + } + + @Override + public IDrawable getIcon() { + return this.icon; } + @OnlyIn(Dist.CLIENT) @Override - public void setRecipe(IRecipeLayout recipeLayout, WrapperAssemblyTable recipeWrapper, 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); - - 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); -// } + public void draw(IAssemblyRecipe recipe, IRecipeSlotsView recipeSlotsView, GuiGraphics guiGraphics, double mouseX, double mouseY) { +// this.progressBar.draw(stack, 81, 2); + this.progressBarMap.get(recipe).draw(guiGraphics, 81, 2); + long mj = recipe.getRequiredMicroJoulesFor(ItemStack.EMPTY); + guiGraphics.drawString(this.font, MjAPI.formatMj(mj) + " MJ", 4, 0, Color.gray.getRGB(), false); + } + + @Override +// public void setRecipe(IRecipeLayout recipeLayout, WrapperAssemblyTable recipeWrapper, IIngredients ingredients) + public void setRecipe(IRecipeLayoutBuilder builder, IAssemblyRecipe recipe, IFocusGroup focuses) { +// IGuiItemStackGroup guiItemStacks = recipeLayout.getItemStacks(); + + // 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) + List inputs = inputsMap.get(recipe); + for (int i = 0; i < inputs.size(); ++i) { +// guiItemStacks.init(i, true, 2 + i % 3 * 18, 11 + i / 3 * 18); +// guiItemStacks.set(i, (List) inputs.get(i)); + builder +// .addSlot(RecipeIngredientRole.INPUT, 2 + i % 3 * 18, 11 + i / 3 * 18) + .addSlot(RecipeIngredientRole.INPUT, 3 + i % 3 * 18, 12 + i / 3 * 18) + .addIngredients(inputs.get(i)); } - guiItemStacks.init(12, false, 110, 11); - guiItemStacks.set(12, ingredients.getOutputs(ItemStack.class).get(0)); +// guiItemStacks.init(12, false, 110, 11); +// guiItemStacks.set(12, (List) ingredients.getOutputs(ItemStack.class).get(0)); + builder +// .addSlot(RecipeIngredientRole.OUTPUT, 110, 11) + .addSlot(RecipeIngredientRole.OUTPUT, 111, 12) + .addIngredients(this.outputsMap.get(recipe)); } } diff --git a/common/buildcraft/compat/module/jei/silicon/CategoryIntegrationTable.java b/common/buildcraft/compat/module/jei/silicon/CategoryIntegrationTable.java index ffe1d16..191ed32 100644 --- a/common/buildcraft/compat/module/jei/silicon/CategoryIntegrationTable.java +++ b/common/buildcraft/compat/module/jei/silicon/CategoryIntegrationTable.java @@ -1,77 +1,131 @@ package buildcraft.compat.module.jei.silicon; +import buildcraft.api.BCModules; +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 mezz.jei.api.constants.VanillaTypes; +import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; +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.IRecipeSlotsView; +import mezz.jei.api.helpers.IGuiHelper; +import mezz.jei.api.recipe.IFocusGroup; +import mezz.jei.api.recipe.RecipeIngredientRole; +import mezz.jei.api.recipe.RecipeType; +import mezz.jei.api.recipe.category.IRecipeCategory; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.level.block.Blocks; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +import java.awt.*; import java.util.List; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; +//public class CategoryIntegrationTable implements IRecipeCategory +public class CategoryIntegrationTable implements IRecipeCategory { + // Calen + public static final RecipeType RECIPE_TYPE = + RecipeType.create(BCModules.SILICON.getModId(), "integration", IntegrationRecipe.class); + // 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; -import buildcraft.api.BCModules; + private final IDrawable icon; -import mezz.jei.api.IGuiHelper; -import mezz.jei.api.gui.IDrawable; -import mezz.jei.api.gui.IGuiItemStackGroup; -import mezz.jei.api.gui.IRecipeLayout; -import mezz.jei.api.ingredients.IIngredients; -import mezz.jei.api.recipe.IRecipeCategory; + private final IntegrationRecipe recipe; + private final IDrawableAnimated progressBar; + private final List inputs; + private final List outputs; -public class CategoryIntegrationTable implements IRecipeCategory { - public static final String UID = "buildcraft-compat:silicon.integration"; + @OnlyIn(Dist.CLIENT) + private Font font = Minecraft.getInstance().font; - protected final ResourceLocation backgroundLocation; - private final IDrawable background; - private WrapperIntegrationTable wrapper = null; + 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(); - 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); + this.icon = guiHelper.createDrawableIngredient(VanillaTypes.ITEM_STACK, 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() { - return UID; + public RecipeType getRecipeType() { + return RECIPE_TYPE; } - @Override - public String getTitle() { - return "Integration Table"; + public Component getTitle() { +// return new TextComponent("Integration Table"); + return Component.translatable("tile.integrationTableBlock.name"); } - @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; + } + + + @OnlyIn(Dist.CLIENT) + @Override + public void draw(IntegrationRecipe recipe, IRecipeSlotsView recipeSlotsView, GuiGraphics guiGraphics, double mouseX, double mouseY) { + this.progressBar.draw(guiGraphics, 156, 1); + guiGraphics.drawString(this.font, MjAPI.formatMj(0L) + " MJ", 80, 52, Color.gray.getRGB()); + + } + + @Override + // public void setRecipe(IRecipeLayout recipeLayout, WrapperIntegrationTable recipeWrapper, IIngredients ingredients) + public void setRecipe(IRecipeLayoutBuilder builder, IntegrationRecipe recipe, IFocusGroup focuses) { +// IGuiItemStackGroup guiItemStacks = recipeLayout.getItemStacks(); +// List> inputs = ingredients.getInputs(ItemStack.class); +// int inventoryIndex = 0; - List> inputs = ingredients.getInputs(ItemStack.class); - 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++; +// guiItemStacks.init(inventoryIndex, true, 19 + x * 25, 24 + y * 25); +// guiItemStacks.set(inventoryIndex, (List) inputs.get(slotIndex)); + builder + .addSlot(RecipeIngredientRole.INPUT, 19 + x * 25, 24 + y * 25) + .addIngredient(VanillaTypes.ITEM_STACK, this.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.init(inventoryIndex, false, 129, 26); +// guiItemStacks.set(inventoryIndex, (List) ingredients.getOutputs(ItemStack.class).get(0)); + builder + .addSlot(RecipeIngredientRole.INPUT, 129, 26) + .addIngredients(Ingredient.of(this.outputs.stream())); +// ++inventoryIndex; } } 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..b7fb4fa 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 com.google.common.collect.Lists; -import net.minecraft.item.ItemStack; import buildcraft.api.recipes.StackDefinition; +import com.google.common.collect.Lists; +import net.minecraft.world.item.ItemStack; + +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..f747716 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 javax.annotation.ParametersAreNonnullByDefault; -import mcp.MethodsReturnNonnullByDefault; +import net.minecraft.MethodsReturnNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; \ No newline at end of file diff --git a/common/buildcraft/compat/module/jei/transferhandlers/AdvancedCraftingItemsTransferHandler.java b/common/buildcraft/compat/module/jei/transferhandlers/AdvancedCraftingItemsTransferHandler.java index 02282e5..b3a4eec 100644 --- a/common/buildcraft/compat/module/jei/transferhandlers/AdvancedCraftingItemsTransferHandler.java +++ b/common/buildcraft/compat/module/jei/transferhandlers/AdvancedCraftingItemsTransferHandler.java @@ -1,34 +1,51 @@ package buildcraft.compat.module.jei.transferhandlers; -import javax.annotation.Nullable; -import net.minecraft.entity.player.EntityPlayer; +import buildcraft.silicon.BCSiliconMenuTypes; import buildcraft.silicon.container.ContainerAdvancedCraftingTable; -import mezz.jei.api.gui.IRecipeLayout; +import mezz.jei.api.constants.RecipeTypes; +import mezz.jei.api.gui.ingredient.IRecipeSlotsView; +import mezz.jei.api.recipe.RecipeType; import mezz.jei.api.recipe.transfer.IRecipeTransferError; import mezz.jei.api.recipe.transfer.IRecipeTransferHandler; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.item.crafting.CraftingRecipe; + +import javax.annotation.Nullable; +import java.util.Optional; + +public class AdvancedCraftingItemsTransferHandler implements IRecipeTransferHandler { + public AdvancedCraftingItemsTransferHandler() { + } -public class AdvancedCraftingItemsTransferHandler implements IRecipeTransferHandler { @Override public Class getContainerClass() { return ContainerAdvancedCraftingTable.class; } - @Nullable @Override - public IRecipeTransferError transferRecipe(ContainerAdvancedCraftingTable container, IRecipeLayout recipeLayout, EntityPlayer player, boolean maxTransfer, boolean doTransfer) { + public Optional> getMenuType() { + return Optional.of(BCSiliconMenuTypes.ADVANCED_CRAFTING_TABLE); + } + + @Override + public RecipeType getRecipeType() { + return RecipeTypes.CRAFTING; + } + + @Override + @Nullable +// public IRecipeTransferError transferRecipe(ContainerAdvancedCraftingTable container, IRecipeLayout recipeLayout, Player player, boolean maxTransfer, boolean doTransfer) + public IRecipeTransferError transferRecipe(ContainerAdvancedCraftingTable container, CraftingRecipe recipe, IRecipeSlotsView recipeSlots, Player 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 + recipe, + recipeSlots + ); } return null; diff --git a/common/buildcraft/compat/module/jei/transferhandlers/AssemblyTableTransferHandler.java b/common/buildcraft/compat/module/jei/transferhandlers/AssemblyTableTransferHandler.java index e0ce8ee..413b9c9 100644 --- a/common/buildcraft/compat/module/jei/transferhandlers/AssemblyTableTransferHandler.java +++ b/common/buildcraft/compat/module/jei/transferhandlers/AssemblyTableTransferHandler.java @@ -1,23 +1,41 @@ package buildcraft.compat.module.jei.transferhandlers; -import javax.annotation.Nullable; -import net.minecraft.entity.player.EntityPlayer; +import buildcraft.api.recipes.IAssemblyRecipe; +import buildcraft.compat.module.jei.silicon.CategoryAssemblyTable; +import buildcraft.silicon.BCSiliconMenuTypes; import buildcraft.silicon.container.ContainerAssemblyTable; -import mezz.jei.api.gui.IRecipeLayout; +import mezz.jei.api.gui.ingredient.IRecipeSlotsView; +import mezz.jei.api.recipe.RecipeType; import mezz.jei.api.recipe.transfer.IRecipeTransferError; import mezz.jei.api.recipe.transfer.IRecipeTransferHandler; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.MenuType; + +import javax.annotation.Nullable; +import java.util.Optional; + +// Calen: never used in 1.12.2? +public class AssemblyTableTransferHandler implements IRecipeTransferHandler { -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 Optional> getMenuType() { + return Optional.of(BCSiliconMenuTypes.ASSEMBLY_TABLE); + } + @Override + public RecipeType getRecipeType() { + return CategoryAssemblyTable.RECIPE_TYPE; + } + @Override + @Nullable +// public IRecipeTransferError transferRecipe(ContainerAssemblyTable container, IRecipeLayout recipeLayout, Player player, boolean maxTransfer, boolean doTransfer) + public IRecipeTransferError transferRecipe(ContainerAssemblyTable container, IAssemblyRecipe recipe, IRecipeSlotsView recipeSlots, Player 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..d31285a 100644 --- a/common/buildcraft/compat/module/jei/transferhandlers/AutoCraftItemsTransferHandler.java +++ b/common/buildcraft/compat/module/jei/transferhandlers/AutoCraftItemsTransferHandler.java @@ -1,53 +1,74 @@ 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.BCFactoryMenuTypes; import buildcraft.factory.container.ContainerAutoCraftItems; -import mezz.jei.api.gui.IGuiIngredient; -import mezz.jei.api.gui.IRecipeLayout; +import com.google.common.collect.Lists; +import mezz.jei.api.constants.RecipeTypes; +import mezz.jei.api.gui.ingredient.IRecipeSlotView; +import mezz.jei.api.gui.ingredient.IRecipeSlotsView; +import mezz.jei.api.recipe.RecipeType; import mezz.jei.api.recipe.transfer.IRecipeTransferError; import mezz.jei.api.recipe.transfer.IRecipeTransferHandler; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.CraftingRecipe; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.Optional; +import java.util.function.Consumer; + +public class AutoCraftItemsTransferHandler implements IRecipeTransferHandler { + public AutoCraftItemsTransferHandler() { + } -public class AutoCraftItemsTransferHandler implements IRecipeTransferHandler { @Override public Class getContainerClass() { return ContainerAutoCraftItems.class; } - @Nullable @Override - public IRecipeTransferError transferRecipe(ContainerAutoCraftItems container, IRecipeLayout recipeLayout, EntityPlayer player, boolean maxTransfer, boolean doTransfer) { + public Optional> getMenuType() { + return Optional.of(BCFactoryMenuTypes.AUTO_WORKBENCH_ITEMS); + } + + @Override + public RecipeType getRecipeType() { + return RecipeTypes.CRAFTING; + } + + @Override + @Nullable +// public IRecipeTransferError transferRecipe(ContainerAutoCraftItems container, IRecipeLayout recipeLayout, Player player, boolean maxTransfer, boolean doTransfer) + public IRecipeTransferError transferRecipe(ContainerAutoCraftItems container, CraftingRecipe recipe, IRecipeSlotsView recipeSlots, Player 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 + recipe, + recipeSlots + ); } return null; } - static void transferRecipe(Consumer> callback, IRecipeLayout recipeLayout) { - Map> inputs = recipeLayout.getItemStacks().getGuiIngredients(); + // static void transferRecipe(Consumer> callback, IRecipeLayout recipeLayout) + static void transferRecipe(Consumer> callback, CraftingRecipe recipe, IRecipeSlotsView recipeLayout) { +// Map> inputs = recipeLayout.getItemStacks().getGuiIngredients(); + List inputs = recipeLayout.getSlotViews(); List stacks = Lists.newArrayList(); - for (int slot = 0; slot < 9; slot++) { - IGuiIngredient ingredient = inputs.getOrDefault(slot + 1, null); - ItemStack stack = (ingredient == null) ? ItemStack.EMPTY : ingredient.getDisplayedIngredient(); - stacks.add((stack == null) ? ItemStack.EMPTY : stack); + + for (int slot = 0; slot < 9; ++slot) { +// IGuiIngredient ingredient = (IGuiIngredient) inputs.getOrDefault(slot + 1, (Object) null); + IRecipeSlotView ingredient = inputs.get(slot + 1); +// ItemStack stack = ingredient == null ? ItemStack.EMPTY : (ItemStack) ingredient.getDisplayedIngredient(); + ItemStack stack = ingredient == null ? ItemStack.EMPTY : (ItemStack) ingredient.getDisplayedIngredient().get().getIngredient(); + stacks.add(stack == null ? ItemStack.EMPTY : stack); } callback.accept(stacks); diff --git a/common/buildcraft/compat/module/jei/transferhandlers/package-info.java b/common/buildcraft/compat/module/jei/transferhandlers/package-info.java index 546f6b9..107bd58 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 javax.annotation.ParametersAreNonnullByDefault; -import mcp.MethodsReturnNonnullByDefault; +import net.minecraft.MethodsReturnNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; \ No newline at end of file diff --git a/common/buildcraft/compat/module/rei/BCPluginREI.java b/common/buildcraft/compat/module/rei/BCPluginREI.java new file mode 100644 index 0000000..4b3d308 --- /dev/null +++ b/common/buildcraft/compat/module/rei/BCPluginREI.java @@ -0,0 +1,110 @@ +package buildcraft.compat.module.rei; + +import buildcraft.api.BCModules; +import buildcraft.api.core.BCLog; +import buildcraft.api.fuels.IFuel; +import buildcraft.api.recipes.IAssemblyRecipe; +import buildcraft.api.recipes.IRefineryRecipeManager; +import buildcraft.compat.module.rei.energy.combustionengine.CategoryCombustionEngine; +import buildcraft.compat.module.rei.energy.combustionengine.DisplayCombustionEngine; +import buildcraft.compat.module.rei.factory.*; +import buildcraft.compat.module.rei.gui.GuiHandlerBuildCraft; +import buildcraft.compat.module.rei.silicon.CategoryAssemblyTable; +import buildcraft.compat.module.rei.silicon.DisplayAssembly; +import buildcraft.core.BCCoreItems; +import buildcraft.factory.BCFactoryBlocks; +import buildcraft.lib.gui.GuiBC8; +import buildcraft.silicon.BCSiliconBlocks; +import buildcraft.silicon.BCSiliconItems; +import buildcraft.transport.item.ItemPipeHolder; +import com.google.common.collect.Lists; +import me.shedaniel.rei.api.client.plugins.REIClientPlugin; +import me.shedaniel.rei.api.client.registry.category.CategoryRegistry; +import me.shedaniel.rei.api.client.registry.display.DisplayRegistry; +import me.shedaniel.rei.api.client.registry.entry.EntryRegistry; +import me.shedaniel.rei.api.client.registry.screen.ExclusionZones; +import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes; +import me.shedaniel.rei.api.common.util.EntryStacks; +import me.shedaniel.rei.forge.REIPluginClient; +import me.shedaniel.rei.plugin.common.BuiltinPlugin; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.fml.ModList; + +import java.util.Arrays; +import java.util.List; + +@REIPluginClient +public class BCPluginREI implements REIClientPlugin { + @Override + public void registerCategories(CategoryRegistry registry) { + boolean factory = ModList.get().isLoaded(BCModules.FACTORY.getModId()); + boolean energy = ModList.get().isLoaded(BCModules.ENERGY.getModId()); + boolean silicon = ModList.get().isLoaded(BCModules.SILICON.getModId()); + List lst = Lists.newArrayList(); + if (factory) { + lst.add("factory"); + registry.add(CategoryHeatable.INSTANCE); + registry.addWorkstations(CategoryHeatable.ID, CategoryHeatable.ICON); + registry.add(CategoryDistiller.INSTANCE); + registry.addWorkstations(CategoryDistiller.ID, CategoryDistiller.ICON); + registry.add(CategoryCoolable.INSTANCE); + registry.addWorkstations(CategoryCoolable.ID, CategoryCoolable.ICON); + + registry.addWorkstations(BuiltinPlugin.CRAFTING, EntryStacks.of(new ItemStack(BCFactoryBlocks.autoWorkbenchItems.get()))); + } + + if (energy) { + lst.add("energy"); + registry.add(CategoryCombustionEngine.INSTANCE); + registry.addWorkstations(CategoryCombustionEngine.ID, CategoryCombustionEngine.ICON); + } + + if (silicon) { + lst.add("silicon"); + registry.add(CategoryAssemblyTable.INSTANCE); + registry.addWorkstations(CategoryAssemblyTable.ID, CategoryAssemblyTable.ICON); + + registry.addWorkstations(BuiltinPlugin.CRAFTING, EntryStacks.of(new ItemStack(BCSiliconBlocks.advancedCraftingTable.get()))); + } + + BCLog.logger.info("Loaded REI mods: " + Arrays.toString(lst.toArray())); + } + + @Override + public void registerDisplays(DisplayRegistry registry) { + registry.registerRecipeFiller(IRefineryRecipeManager.IHeatableRecipe.class, IRefineryRecipeManager.IHeatableRecipe.TYPE, DisplayHeatable::new); + registry.registerRecipeFiller(IRefineryRecipeManager.IDistillationRecipe.class, IRefineryRecipeManager.IDistillationRecipe.TYPE, DisplayDistillation::new); + registry.registerRecipeFiller(IRefineryRecipeManager.ICoolableRecipe.class, IRefineryRecipeManager.ICoolableRecipe.TYPE, DisplayCoolable::new); + registry.registerRecipeFiller(IFuel.class, IFuel.TYPE, DisplayCombustionEngine::new); + registry.registerRecipeFiller(IAssemblyRecipe.class, IAssemblyRecipe.TYPE, DisplayAssembly::new); + } + + @Override + public void registerExclusionZones(ExclusionZones zones) { + zones.register(GuiBC8.class, new GuiHandlerBuildCraft()); + } + + @Override + public void registerEntries(EntryRegistry registry) { + registry.removeEntryIf(entryStack -> { + if (entryStack.getType() == VanillaEntryTypes.ITEM) { + ItemStack itemStack = entryStack.castValue(); + Item item = itemStack.getItem(); + if (item == BCCoreItems.fragileFluidShard.get()) { + return true; + } else if (item instanceof ItemPipeHolder pipe) { + // TODO if disable colored piped + if (pipe.getColour() != DyeColor.WHITE) { + return true; + } + } else if (item == BCSiliconItems.plugFacade.get()) { + // TODO if disable rei facades + return true; + } + } + return false; + }); + } +} diff --git a/common/buildcraft/compat/module/rei/ReiUtils.java b/common/buildcraft/compat/module/rei/ReiUtils.java new file mode 100644 index 0000000..db6fdbe --- /dev/null +++ b/common/buildcraft/compat/module/rei/ReiUtils.java @@ -0,0 +1,61 @@ +package buildcraft.compat.module.rei; + +import com.mojang.blaze3d.systems.RenderSystem; +import me.shedaniel.math.Point; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; + +public class ReiUtils { + public static final int PADDING = 5; + + public static void drawAnimation(GuiGraphics graphics, Point lu, ResourceLocation rl, int ticksPerCycle, int x, int y, int u, int v, int fullWidth, int fullHeight, ReiUtils.StartPosition startPosition) { + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.enableBlend(); + RenderSystem.blendFuncSeparate(770, 771, 1, 0); + RenderSystem.blendFunc(770, 771); + final double width_double = fullWidth; + final double height_double = fullHeight; + if (startPosition == StartPosition.LEFT) { + int width = Mth.ceil((System.currentTimeMillis() / (ticksPerCycle * 50 / width_double) % fullWidth)); + graphics.blit( + rl, + lu.getX() + x, lu.getY() + y, + u, v, + width, fullHeight + ); + } else if (startPosition == StartPosition.RIGHT) { + int width = Mth.ceil((System.currentTimeMillis() / (ticksPerCycle * 50 / width_double) % fullWidth)); + graphics.blit( + rl, + lu.getX() + x + fullWidth - width, lu.getY() + y, + u + fullWidth - width, v, + width, fullHeight + ); + } else if (startPosition == StartPosition.TOP) { + int height = Mth.ceil((System.currentTimeMillis() / (ticksPerCycle * 50 / height_double) % fullHeight)); + graphics.blit( + rl, + lu.getX() + x, lu.getY() + y, + u, v, + fullWidth, height + ); + } else if (startPosition == StartPosition.BOTTOM) { + int height = Mth.ceil((System.currentTimeMillis() / (ticksPerCycle * 50 / height_double) % fullHeight)); + graphics.blit( + rl, + lu.getX() + x, lu.getY() + y + fullHeight - height, + u, v + fullHeight - height, + fullWidth, height + ); + } + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + } + + public static enum StartPosition { + LEFT, + RIGHT, + TOP, + BOTTOM; + } +} diff --git a/common/buildcraft/compat/module/rei/energy/combustionengine/CategoryCombustionEngine.java b/common/buildcraft/compat/module/rei/energy/combustionengine/CategoryCombustionEngine.java new file mode 100644 index 0000000..a498cd5 --- /dev/null +++ b/common/buildcraft/compat/module/rei/energy/combustionengine/CategoryCombustionEngine.java @@ -0,0 +1,114 @@ +package buildcraft.compat.module.rei.energy.combustionengine; + +import buildcraft.api.BCModules; +import buildcraft.api.mj.MjAPI; +import buildcraft.compat.module.rei.ReiUtils; +import buildcraft.energy.BCEnergyBlocks; +import com.google.common.collect.Lists; +import com.mojang.blaze3d.vertex.PoseStack; +import me.shedaniel.math.Point; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.gui.Renderer; +import me.shedaniel.rei.api.client.gui.widgets.Widget; +import me.shedaniel.rei.api.client.gui.widgets.Widgets; +import me.shedaniel.rei.api.client.registry.display.DisplayCategory; +import me.shedaniel.rei.api.common.category.CategoryIdentifier; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.util.EntryStacks; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; + +import java.awt.*; +import java.util.List; + +public enum CategoryCombustionEngine implements DisplayCategory { + INSTANCE; + + public static final CategoryIdentifier ID = CategoryIdentifier.of(new ResourceLocation(BCModules.ENERGY.getModId(), "category_engine_combustion")); + public static final EntryStack ICON = EntryStacks.of(new ItemStack(BCEnergyBlocks.engineIron.get())); + public static final ResourceLocation BACKGROUND = new ResourceLocation("minecraft", "textures/gui/container/furnace.png"); + + @Override + public CategoryIdentifier getCategoryIdentifier() { + return ID; + } + + @Override + public Component getTitle() { + return Component.translatable("buildcraft.rei.title.combustion_engine_fuels"); + } + + @Override + public Renderer getIcon() { + return ICON; + } + + @Override + public int getDisplayHeight() { + return 32 + 2 + ReiUtils.PADDING * 2; + } + + @Override + public int getDisplayWidth(DisplayCombustionEngine display) { + return 138 + 2 + ReiUtils.PADDING * 2; + } + + @Override + public List setupDisplay(DisplayCombustionEngine display, Rectangle bounds) { + List ret = Lists.newArrayList(); + + ret.add(Widgets.createRecipeBase(bounds)); + + Point lu = new Point(bounds.getX() + ReiUtils.PADDING, bounds.getY() + ReiUtils.PADDING); + + // background + ret.add(Widgets.createTexturedWidget(BACKGROUND, lu.getX() + 0, lu.getY() + 0, 55, 38, 18, 32)); + + // slot + if (!display.getOutputEntries().isEmpty()) { + ret.add(Widgets.createTexturedWidget(BACKGROUND, lu.getX() + 114, lu.getY() + 14, 7, 22, 18, 18)); + } + + // animation + ret.add(Widgets.createDrawableWidget((guiGraphics, mouseX, mouseY, delta) -> + ReiUtils.drawAnimation( + guiGraphics, lu, BACKGROUND, + display.totalBurningTime / 10, + 2, 0, + 176, 0, + 14, 14, + ReiUtils.StartPosition.BOTTOM + ) + )); + + // slot content + ret.add(Widgets.createSlot(new Point(lu.getX() + 1, lu.getY() + 15)).markInput().entries(display.getInputEntries().get(0)).disableBackground()); + if (!display.getOutputEntries().isEmpty()) { + ret.add(Widgets.createSlot(new Point(lu.getX() + 115, lu.getY() + 15)).markOutput().entries(display.getOutputEntries().get(0)).disableBackground()); + } + + // text + ret.add(Widgets.createDrawableWidget((guiGraphics, mouseX, mouseY, delta) -> + { + PoseStack poseStack = guiGraphics.pose(); + poseStack.pushPose(); + poseStack.translate(lu.getX(), lu.getY(), 0); + Font font = Minecraft.getInstance().font; + + poseStack.pushPose(); + poseStack.translate(24.0F, 6.0F, 0.0F); + guiGraphics.drawString(font, Component.translatable("buildcraft.jei.title.combustion_engine_fuels.burn_time", display.totalBurningTime / 20).getString(), 0, 0, Color.darkGray.getRGB(), false); + guiGraphics.drawString(font, Component.translatable("buildcraft.jei.title.combustion_engine_fuels.burn_speed", MjAPI.formatMj(display.powerPerCycle)).getString(), 0, font.lineHeight, Color.darkGray.getRGB(), false); + poseStack.translate(0.0F, (float) (font.lineHeight * 2), 0.0F); + poseStack.scale(0.7F, 0.7F, 1.0F); + guiGraphics.drawString(font, Component.translatable("buildcraft.jei.title.combustion_engine_fuels.burn_total", MjAPI.formatMj(display.powerPerCycle * (long) display.totalBurningTime)).getString(), 1, 2, Color.gray.getRGB(), false); + poseStack.popPose(); + poseStack.popPose(); + })); + + return ret; + } +} diff --git a/common/buildcraft/compat/module/rei/energy/combustionengine/DisplayCombustionEngine.java b/common/buildcraft/compat/module/rei/energy/combustionengine/DisplayCombustionEngine.java new file mode 100644 index 0000000..ffdfc4a --- /dev/null +++ b/common/buildcraft/compat/module/rei/energy/combustionengine/DisplayCombustionEngine.java @@ -0,0 +1,48 @@ +package buildcraft.compat.module.rei.energy.combustionengine; + +import buildcraft.api.fuels.IFuel; +import buildcraft.api.fuels.IFuelManager; +import dev.architectury.fluid.FluidStack; +import me.shedaniel.rei.api.common.category.CategoryIdentifier; +import me.shedaniel.rei.api.common.display.Display; +import me.shedaniel.rei.api.common.entry.EntryIngredient; +import me.shedaniel.rei.api.common.util.EntryIngredients; + +import java.util.List; + +public class DisplayCombustionEngine implements Display { + private final EntryIngredient fluid; + private final EntryIngredient residue; + public final int totalBurningTime; + public final long powerPerCycle; + + public DisplayCombustionEngine(IFuel recipe) { + totalBurningTime = recipe.getTotalBurningTime(); + powerPerCycle = recipe.getPowerPerCycle(); + fluid = EntryIngredients.of(FluidStack.create(recipe.getFluid().getRawFluid(), recipe.getFluid().getAmount())); + if (recipe instanceof IFuelManager.IDirtyFuel dirtyFuel) { + residue = EntryIngredients.of(FluidStack.create(dirtyFuel.getResidue().getRawFluid(), dirtyFuel.getResidue().getAmount())); + } else { + residue = null; + } + } + + @Override + public List getInputEntries() { + return List.of(fluid); + } + + @Override + public List getOutputEntries() { + if (residue == null) { + return List.of(); + } else { + return List.of(residue); + } + } + + @Override + public CategoryIdentifier getCategoryIdentifier() { + return CategoryCombustionEngine.ID; + } +} diff --git a/common/buildcraft/compat/module/rei/factory/CategoryCoolable.java b/common/buildcraft/compat/module/rei/factory/CategoryCoolable.java new file mode 100644 index 0000000..adda395 --- /dev/null +++ b/common/buildcraft/compat/module/rei/factory/CategoryCoolable.java @@ -0,0 +1,97 @@ +package buildcraft.compat.module.rei.factory; + +import buildcraft.api.BCModules; +import buildcraft.compat.module.rei.ReiUtils; +import buildcraft.factory.BCFactoryBlocks; +import com.google.common.collect.Lists; +import me.shedaniel.math.Point; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.gui.Renderer; +import me.shedaniel.rei.api.client.gui.widgets.Widget; +import me.shedaniel.rei.api.client.gui.widgets.Widgets; +import me.shedaniel.rei.api.client.registry.display.DisplayCategory; +import me.shedaniel.rei.api.common.category.CategoryIdentifier; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.util.EntryStacks; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; + +import java.util.List; + +public enum CategoryCoolable implements DisplayCategory { + INSTANCE; + + public static final CategoryIdentifier ID = CategoryIdentifier.of(new ResourceLocation(BCModules.FACTORY.getModId(), "category_coolable")); + public static final EntryStack ICON = EntryStacks.of(new ItemStack(BCFactoryBlocks.heatExchange.get())); + public static final ResourceLocation BACKGROUND = new ResourceLocation(BCModules.FACTORY.getModId(), "textures/gui/heat_exchanger.png"); + + @Override + public CategoryIdentifier getCategoryIdentifier() { + return ID; + } + + @Override + public Component getTitle() { + return Component.translatable("buildcraft.rei.title.coolable_fluids"); + } + + @Override + public Renderer getIcon() { + return ICON; + } + + @Override + public int getDisplayHeight() { + return 17 + 2 + ReiUtils.PADDING * 2; + } + + @Override + public int getDisplayWidth(DisplayCoolable display) { + return 90 + 2 + ReiUtils.PADDING * 2; + } + + @Override + public List setupDisplay(DisplayCoolable display, Rectangle bounds) { + List ret = Lists.newArrayList(); + + ret.add(Widgets.createRecipeBase(bounds)); + + Point lu = new Point(bounds.getX() + ReiUtils.PADDING, bounds.getY() + ReiUtils.PADDING); + + // background + ret.add(Widgets.createTexturedWidget(BACKGROUND, lu.getX() + 18, lu.getY() + 2, 61, 38, 54, 17)); + + // slot + ret.add(Widgets.createTexturedWidget(BACKGROUND, lu.getX() + 0, lu.getY() + 1, 7, 22, 18, 18)); + ret.add(Widgets.createTexturedWidget(BACKGROUND, lu.getX() + 72, lu.getY() + 1, 7, 22, 18, 18)); + + // animation + ret.add(Widgets.createDrawableWidget((guiGraphics, mouseX, mouseY, delta) -> + ReiUtils.drawAnimation( + guiGraphics, lu, BACKGROUND, + 40, + 18, 2, + 52, 171, + 54, 17, + ReiUtils.StartPosition.LEFT + ) + )); + ret.add(Widgets.createDrawableWidget((guiGraphics, mouseX, mouseY, delta) -> + ReiUtils.drawAnimation( + guiGraphics, lu, BACKGROUND, + 40, + 18, 2, + 52, 188, + 54, 17, + ReiUtils.StartPosition.RIGHT + ) + )); + + // slot content + ret.add(Widgets.createSlot(new Point(lu.getX() + 1, lu.getY() + 2)).markInput().entries(display.getInputEntries().get(0)).disableBackground()); + ret.add(Widgets.createSlot(new Point(lu.getX() + 73, lu.getY() + 2)).markOutput().entries(display.getOutputEntries().get(0)).disableBackground()); + + return ret; + } +} diff --git a/common/buildcraft/compat/module/rei/factory/CategoryDistiller.java b/common/buildcraft/compat/module/rei/factory/CategoryDistiller.java new file mode 100644 index 0000000..cab10c1 --- /dev/null +++ b/common/buildcraft/compat/module/rei/factory/CategoryDistiller.java @@ -0,0 +1,105 @@ +package buildcraft.compat.module.rei.factory; + +import buildcraft.api.BCModules; +import buildcraft.api.mj.MjAPI; +import buildcraft.compat.module.rei.ReiUtils; +import buildcraft.factory.BCFactoryBlocks; +import com.google.common.collect.Lists; +import com.mojang.blaze3d.vertex.PoseStack; +import me.shedaniel.math.Point; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.gui.Renderer; +import me.shedaniel.rei.api.client.gui.widgets.Widget; +import me.shedaniel.rei.api.client.gui.widgets.Widgets; +import me.shedaniel.rei.api.client.registry.display.DisplayCategory; +import me.shedaniel.rei.api.common.category.CategoryIdentifier; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.util.EntryStacks; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; + +import java.awt.*; +import java.util.List; + +public enum CategoryDistiller implements DisplayCategory { + INSTANCE; + + public static final CategoryIdentifier ID = CategoryIdentifier.of(new ResourceLocation(BCModules.FACTORY.getModId(), "category_distiller")); + public static final EntryStack ICON = EntryStacks.of(new ItemStack(BCFactoryBlocks.distiller.get())); + public static final ResourceLocation BACKGROUND = new ResourceLocation(BCModules.FACTORY.getModId(), "textures/gui/distiller.png"); + + @Override + public CategoryIdentifier getCategoryIdentifier() { + return ID; + } + + @Override + public Component getTitle() { + return Component.translatable("buildcraft.rei.title.distillable_fluids"); + } + + @Override + public Renderer getIcon() { + return ICON; + } + + @Override + public int getDisplayHeight() { + return 65 + 2 + ReiUtils.PADDING * 2; + } + + @Override + public int getDisplayWidth(DisplayDistillation display) { + return 90 + 2 + ReiUtils.PADDING * 2; + } + + @Override + public List setupDisplay(DisplayDistillation display, Rectangle bounds) { + List ret = Lists.newArrayList(); + + ret.add(Widgets.createRecipeBase(bounds)); + + Point lu = new Point(bounds.getX() + ReiUtils.PADDING, bounds.getY() + ReiUtils.PADDING); + + // background + ret.add(Widgets.createTexturedWidget(BACKGROUND, lu.getX() + 20, lu.getY() + 4, 61, 12, 36, 57)); + + // slot + ret.add(Widgets.createTexturedWidget(BACKGROUND, lu.getX() + 0, lu.getY() + 25, 7, 34, 18, 18)); + ret.add(Widgets.createTexturedWidget(BACKGROUND, lu.getX() + 56, lu.getY() + 0, 7, 34, 18, 18)); + ret.add(Widgets.createTexturedWidget(BACKGROUND, lu.getX() + 56, lu.getY() + 45, 7, 34, 18, 18)); + + // animation + ret.add(Widgets.createDrawableWidget((guiGraphics, mouseX, mouseY, delta) -> + ReiUtils.drawAnimation( + guiGraphics, lu, BACKGROUND, + 40, + 20, 4, + 212, 0, + 36, 57, + ReiUtils.StartPosition.LEFT + ) + )); + + // text + ret.add(Widgets.createDrawableWidget((guiGraphics, mouseX, mouseY, delta) -> + { + PoseStack poseStack = guiGraphics.pose(); + poseStack.pushPose(); + poseStack.translate(lu.getX(), lu.getY(), 0); + Font font = Minecraft.getInstance().font; + guiGraphics.drawString(font, MjAPI.formatMj(display.powerRequired) + " MJ", 58, 28, Color.CYAN.getRGB()); + poseStack.popPose(); + })); + + // slot content + ret.add(Widgets.createSlot(new Point(lu.getX() + 1, lu.getY() + 26)).markInput().entries(display.getInputEntries().get(0)).disableBackground()); + ret.add(Widgets.createSlot(new Point(lu.getX() + 57, lu.getY() + 1)).markOutput().entries(display.getOutputEntries().get(0)).disableBackground()); + ret.add(Widgets.createSlot(new Point(lu.getX() + 57, lu.getY() + 46)).markOutput().entries(display.getOutputEntries().get(1)).disableBackground()); + + return ret; + } +} diff --git a/common/buildcraft/compat/module/rei/factory/CategoryHeatable.java b/common/buildcraft/compat/module/rei/factory/CategoryHeatable.java new file mode 100644 index 0000000..c5f20ed --- /dev/null +++ b/common/buildcraft/compat/module/rei/factory/CategoryHeatable.java @@ -0,0 +1,87 @@ +package buildcraft.compat.module.rei.factory; + +import buildcraft.api.BCModules; +import buildcraft.compat.module.rei.ReiUtils; +import buildcraft.factory.BCFactoryBlocks; +import com.google.common.collect.Lists; +import me.shedaniel.math.Point; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.gui.Renderer; +import me.shedaniel.rei.api.client.gui.widgets.Widget; +import me.shedaniel.rei.api.client.gui.widgets.Widgets; +import me.shedaniel.rei.api.client.registry.display.DisplayCategory; +import me.shedaniel.rei.api.common.category.CategoryIdentifier; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.util.EntryStacks; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; + +import java.util.List; + +public enum CategoryHeatable implements DisplayCategory { + INSTANCE; + + public static final CategoryIdentifier ID = CategoryIdentifier.of(new ResourceLocation(BCModules.FACTORY.getModId(), "category_heatable")); + public static final EntryStack ICON = EntryStacks.of(new ItemStack(BCFactoryBlocks.heatExchange.get())); + public static final ResourceLocation BACKGROUND = new ResourceLocation(BCModules.FACTORY.getModId(), "textures/gui/energy_heater.png"); + + @Override + public CategoryIdentifier getCategoryIdentifier() { + return ID; + } + + @Override + public Component getTitle() { + return Component.translatable("buildcraft.rei.title.heatable_fluids"); + } + + @Override + public Renderer getIcon() { + return ICON; + } + + @Override + public int getDisplayHeight() { + return 17 + 2 + ReiUtils.PADDING * 2; + } + + @Override + public int getDisplayWidth(DisplayHeatable display) { + return 90 + 2 + ReiUtils.PADDING * 2; + } + + @Override + public List setupDisplay(DisplayHeatable display, Rectangle bounds) { + List ret = Lists.newArrayList(); + + ret.add(Widgets.createRecipeBase(bounds)); + + Point lu = new Point(bounds.getX() + ReiUtils.PADDING, bounds.getY() + ReiUtils.PADDING); + + // background + ret.add(Widgets.createTexturedWidget(BACKGROUND, lu.getX() + 18, lu.getY() + 0, 176, 19, 54, 19)); + + // slot + ret.add(Widgets.createTexturedWidget(BACKGROUND, lu.getX() + 0, lu.getY() + 1, 7, 22, 18, 18)); + ret.add(Widgets.createTexturedWidget(BACKGROUND, lu.getX() + 72, lu.getY() + 1, 7, 22, 18, 18)); + + // animation + ret.add(Widgets.createDrawableWidget((guiGraphics, mouseX, mouseY, delta) -> + ReiUtils.drawAnimation( + guiGraphics, lu, BACKGROUND, + 40, + 18, 0, + 176, 152, + 54, 19, + ReiUtils.StartPosition.LEFT + ) + )); + + // slot content + ret.add(Widgets.createSlot(new Point(lu.getX() + 1, lu.getY() + 2)).markInput().entries(display.getInputEntries().get(0)).disableBackground()); + ret.add(Widgets.createSlot(new Point(lu.getX() + 73, lu.getY() + 2)).markOutput().entries(display.getOutputEntries().get(0)).disableBackground()); + + return ret; + } +} diff --git a/common/buildcraft/compat/module/rei/factory/DisplayCoolable.java b/common/buildcraft/compat/module/rei/factory/DisplayCoolable.java new file mode 100644 index 0000000..9b1d9dc --- /dev/null +++ b/common/buildcraft/compat/module/rei/factory/DisplayCoolable.java @@ -0,0 +1,35 @@ +package buildcraft.compat.module.rei.factory; + +import buildcraft.api.recipes.IRefineryRecipeManager; +import dev.architectury.fluid.FluidStack; +import me.shedaniel.rei.api.common.category.CategoryIdentifier; +import me.shedaniel.rei.api.common.display.Display; +import me.shedaniel.rei.api.common.entry.EntryIngredient; +import me.shedaniel.rei.api.common.util.EntryIngredients; + +import java.util.List; + +public class DisplayCoolable implements Display { + private final EntryIngredient in; + private final EntryIngredient out; + + public DisplayCoolable(IRefineryRecipeManager.ICoolableRecipe recipe) { + in = EntryIngredients.of(FluidStack.create(recipe.in().getRawFluid(), recipe.in().getAmount())); + out = EntryIngredients.of(FluidStack.create(recipe.out().getRawFluid(), recipe.out().getAmount())); + } + + @Override + public List getInputEntries() { + return List.of(in); + } + + @Override + public List getOutputEntries() { + return List.of(out); + } + + @Override + public CategoryIdentifier getCategoryIdentifier() { + return CategoryCoolable.ID; + } +} diff --git a/common/buildcraft/compat/module/rei/factory/DisplayDistillation.java b/common/buildcraft/compat/module/rei/factory/DisplayDistillation.java new file mode 100644 index 0000000..c6853d8 --- /dev/null +++ b/common/buildcraft/compat/module/rei/factory/DisplayDistillation.java @@ -0,0 +1,39 @@ +package buildcraft.compat.module.rei.factory; + +import buildcraft.api.recipes.IRefineryRecipeManager; +import dev.architectury.fluid.FluidStack; +import me.shedaniel.rei.api.common.category.CategoryIdentifier; +import me.shedaniel.rei.api.common.display.Display; +import me.shedaniel.rei.api.common.entry.EntryIngredient; +import me.shedaniel.rei.api.common.util.EntryIngredients; + +import java.util.List; + +public class DisplayDistillation implements Display { + private final EntryIngredient in; + private final EntryIngredient outGas; + private final EntryIngredient outLiquid; + public final long powerRequired; + + public DisplayDistillation(IRefineryRecipeManager.IDistillationRecipe recipe) { + in = EntryIngredients.of(FluidStack.create(recipe.in().getRawFluid(), recipe.in().getAmount())); + outGas = EntryIngredients.of(FluidStack.create(recipe.outGas().getRawFluid(), recipe.outGas().getAmount())); + outLiquid = EntryIngredients.of(FluidStack.create(recipe.outLiquid().getRawFluid(), recipe.outLiquid().getAmount())); + powerRequired = recipe.powerRequired(); + } + + @Override + public List getInputEntries() { + return List.of(in); + } + + @Override + public List getOutputEntries() { + return List.of(outGas, outLiquid); + } + + @Override + public CategoryIdentifier getCategoryIdentifier() { + return CategoryDistiller.ID; + } +} diff --git a/common/buildcraft/compat/module/rei/factory/DisplayHeatable.java b/common/buildcraft/compat/module/rei/factory/DisplayHeatable.java new file mode 100644 index 0000000..78ee10d --- /dev/null +++ b/common/buildcraft/compat/module/rei/factory/DisplayHeatable.java @@ -0,0 +1,35 @@ +package buildcraft.compat.module.rei.factory; + +import buildcraft.api.recipes.IRefineryRecipeManager; +import dev.architectury.fluid.FluidStack; +import me.shedaniel.rei.api.common.category.CategoryIdentifier; +import me.shedaniel.rei.api.common.display.Display; +import me.shedaniel.rei.api.common.entry.EntryIngredient; +import me.shedaniel.rei.api.common.util.EntryIngredients; + +import java.util.List; + +public class DisplayHeatable implements Display { + private final EntryIngredient in; + private final EntryIngredient out; + + public DisplayHeatable(IRefineryRecipeManager.IHeatableRecipe recipe) { + in = EntryIngredients.of(FluidStack.create(recipe.in().getRawFluid(), recipe.in().getAmount())); + out = EntryIngredients.of(FluidStack.create(recipe.out().getRawFluid(), recipe.out().getAmount())); + } + + @Override + public List getInputEntries() { + return List.of(in); + } + + @Override + public List getOutputEntries() { + return List.of(out); + } + + @Override + public CategoryIdentifier getCategoryIdentifier() { + return CategoryHeatable.ID; + } +} diff --git a/common/buildcraft/compat/module/rei/gui/GuiHandlerBuildCraft.java b/common/buildcraft/compat/module/rei/gui/GuiHandlerBuildCraft.java new file mode 100644 index 0000000..bc4b0e9 --- /dev/null +++ b/common/buildcraft/compat/module/rei/gui/GuiHandlerBuildCraft.java @@ -0,0 +1,32 @@ +package buildcraft.compat.module.rei.gui; + +import buildcraft.lib.gui.GuiBC8; +import buildcraft.lib.gui.IGuiElement; +import buildcraft.lib.gui.pos.GuiRectangle; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.registry.screen.ExclusionZonesProvider; +import net.minecraft.util.Mth; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class GuiHandlerBuildCraft implements ExclusionZonesProvider> { + @Override + public Collection provide(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 = Mth.ceil(rect.getEndX()); + int endY = Mth.ceil(rect.getEndY()); + int width = endX - x; + int height = endY - y; + list.add(new Rectangle(x, y, width, height)); + } + + return list; + } +} diff --git a/common/buildcraft/compat/module/rei/silicon/CategoryAssemblyTable.java b/common/buildcraft/compat/module/rei/silicon/CategoryAssemblyTable.java new file mode 100644 index 0000000..7c3a813 --- /dev/null +++ b/common/buildcraft/compat/module/rei/silicon/CategoryAssemblyTable.java @@ -0,0 +1,102 @@ +package buildcraft.compat.module.rei.silicon; + +import buildcraft.api.BCModules; +import buildcraft.api.mj.MjAPI; +import buildcraft.compat.module.rei.ReiUtils; +import buildcraft.silicon.BCSiliconBlocks; +import com.google.common.collect.Lists; +import com.mojang.blaze3d.vertex.PoseStack; +import me.shedaniel.math.Point; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.gui.Renderer; +import me.shedaniel.rei.api.client.gui.widgets.Widget; +import me.shedaniel.rei.api.client.gui.widgets.Widgets; +import me.shedaniel.rei.api.client.registry.display.DisplayCategory; +import me.shedaniel.rei.api.common.category.CategoryIdentifier; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.util.EntryStacks; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; + +import java.awt.*; +import java.util.List; + +public enum CategoryAssemblyTable implements DisplayCategory { + INSTANCE; + + public static final CategoryIdentifier ID = CategoryIdentifier.of(new ResourceLocation(BCModules.SILICON.getModId(), "category_assembly")); + public static final EntryStack ICON = EntryStacks.of(new ItemStack(BCSiliconBlocks.assemblyTable.get())); + public static final ResourceLocation BACKGROUND = new ResourceLocation(BCModules.SILICON.getModId(), "textures/gui/assembly_table.png"); + + @Override + public CategoryIdentifier getCategoryIdentifier() { + return ID; + } + + @Override + public Component getTitle() { + return Component.translatable("tile.assemblyTableBlock.name"); + } + + @Override + public Renderer getIcon() { + return ICON; + } + + @Override + public int getDisplayHeight() { + return 86 + 2 + ReiUtils.PADDING * 2; + } + + @Override + public int getDisplayWidth(DisplayAssembly display) { + return 166 + 2 + ReiUtils.PADDING * 2; + } + + @Override + public List setupDisplay(DisplayAssembly display, Rectangle bounds) { + List ret = Lists.newArrayList(); + + ret.add(Widgets.createRecipeBase(bounds)); + + Point lu = new Point(bounds.getX() + ReiUtils.PADDING, bounds.getY() + ReiUtils.PADDING); + + // background + ret.add(Widgets.createTexturedWidget(BACKGROUND, lu.getX() + 0, lu.getY() + 10, 5, 34, 166, 76)); + + // animation + ret.add(Widgets.createDrawableWidget((guiGraphics, mouseX, mouseY, delta) -> + ReiUtils.drawAnimation( + guiGraphics, lu, BACKGROUND, + (int) Math.max(10L, display.requiredMicroJoules / MjAPI.MJ / 50L), + 81, 12, + 176, 48, + 4, 71, + ReiUtils.StartPosition.BOTTOM + ) + )); + + // text + ret.add(Widgets.createDrawableWidget((guiGraphics, mouseX, mouseY, delta) -> + { + PoseStack poseStack = guiGraphics.pose(); + poseStack.pushPose(); + poseStack.translate(lu.getX(), lu.getY(), 0); + Font font = Minecraft.getInstance().font; + long mj = display.requiredMicroJoules; + guiGraphics.drawString(font, MjAPI.formatMj(mj) + " MJ", 4, 0, Color.gray.getRGB(), false); + poseStack.popPose(); + })); + + // slot content + for (int i = 0; i < display.getInputEntries().size(); ++i) { + ret.add(Widgets.createSlot(new Point(lu.getX() + 3 + i % 3 * 18, lu.getY() + 12 + i / 3 * 18)).markInput().entries(display.getInputEntries().get(i)).disableBackground()); + } + ret.add(Widgets.createSlot(new Point(lu.getX() + 111, lu.getY() + 12)).markOutput().entries(display.getOutputEntries().get(0)).disableBackground()); + + return ret; + } +} diff --git a/common/buildcraft/compat/module/rei/silicon/CategoryIntegrationTable.java b/common/buildcraft/compat/module/rei/silicon/CategoryIntegrationTable.java new file mode 100644 index 0000000..c812461 --- /dev/null +++ b/common/buildcraft/compat/module/rei/silicon/CategoryIntegrationTable.java @@ -0,0 +1,4 @@ +package buildcraft.compat.module.rei.silicon; + +public class CategoryIntegrationTable { +} diff --git a/common/buildcraft/compat/module/rei/silicon/DisplayAssembly.java b/common/buildcraft/compat/module/rei/silicon/DisplayAssembly.java new file mode 100644 index 0000000..97b3fb4 --- /dev/null +++ b/common/buildcraft/compat/module/rei/silicon/DisplayAssembly.java @@ -0,0 +1,36 @@ +package buildcraft.compat.module.rei.silicon; + +import buildcraft.api.recipes.IAssemblyRecipe; +import me.shedaniel.rei.api.common.category.CategoryIdentifier; +import me.shedaniel.rei.api.common.display.Display; +import me.shedaniel.rei.api.common.entry.EntryIngredient; +import me.shedaniel.rei.api.common.util.EntryIngredients; + +import java.util.List; + +public class DisplayAssembly implements Display { + private final List in; + private final EntryIngredient out; + public final long requiredMicroJoules; + + public DisplayAssembly(IAssemblyRecipe recipe) { + in = EntryIngredients.ofIngredients(recipe.getRequiredIngredientStacks().stream().map(ingredientStack -> ingredientStack.ingredient).toList()); + out = EntryIngredients.of(recipe.getOutput().stream().toList().get(0)); + requiredMicroJoules = recipe.getRequiredMicroJoules(); + } + + @Override + public List getInputEntries() { + return in; + } + + @Override + public List getOutputEntries() { + return List.of(out); + } + + @Override + public CategoryIdentifier getCategoryIdentifier() { + return CategoryAssemblyTable.ID; + } +} diff --git a/common/buildcraft/compat/module/rei/silicon/DisplayIntegration.java b/common/buildcraft/compat/module/rei/silicon/DisplayIntegration.java new file mode 100644 index 0000000..0330e39 --- /dev/null +++ b/common/buildcraft/compat/module/rei/silicon/DisplayIntegration.java @@ -0,0 +1,29 @@ +package buildcraft.compat.module.rei.silicon; + +import buildcraft.api.recipes.IIntegrationRecipeProvider; +import me.shedaniel.rei.api.common.category.CategoryIdentifier; +import me.shedaniel.rei.api.common.display.Display; +import me.shedaniel.rei.api.common.entry.EntryIngredient; + +import java.util.List; + +public class DisplayIntegration implements Display { + + public DisplayIntegration(IIntegrationRecipeProvider recipe) { + } + + @Override + public List getInputEntries() { + return List.of(); + } + + @Override + public List getOutputEntries() { + return List.of(); + } + + @Override + public CategoryIdentifier getCategoryIdentifier() { + throw new RuntimeException(); + } +} diff --git a/common/buildcraft/compat/module/theoneprobe/BCPluginTOP.java b/common/buildcraft/compat/module/theoneprobe/BCPluginTOP.java index 947e923..c9f414d 100644 --- a/common/buildcraft/compat/module/theoneprobe/BCPluginTOP.java +++ b/common/buildcraft/compat/module/theoneprobe/BCPluginTOP.java @@ -1,72 +1,62 @@ package buildcraft.compat.module.theoneprobe; -import static buildcraft.compat.module.theoneprobe.BCPluginTOP.TOP_MOD_ID; - -import java.util.List; - -import com.google.common.base.Function; - -import net.minecraft.block.state.IBlockState; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.ItemStack; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.text.TextFormatting; -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 buildcraft.lib.misc.BlockUtil; +import buildcraft.lib.tile.craft.IAssemblyCraft; +import buildcraft.lib.tile.craft.IAutoCraft; +import com.google.common.base.Function; +import mcjty.theoneprobe.api.*; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; -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, Player player, Level world, BlockState blockState, IProbeHitData data) { return false; } - @Override - @Optional.Method(modid = TOP_MOD_ID) - public String getID() { - return "buildcraftcompat.top"; + // @Method(modid = "theoneprobe") + // public String getID() + public ResourceLocation getID() { +// return "buildcraftcompat.top"; + return new ResourceLocation("buildcraftcompat.top"); } - @Override - @Optional.Method(modid = TOP_MOD_ID) - public void addProbeInfo(ProbeMode mode, IProbeInfo probeInfo, EntityPlayer player, World world, IBlockState blockState, IProbeHitData data) { - ResourceLocation blockRegistryName = blockState.getBlock().getRegistryName(); - if ((blockRegistryName != null) && (BCModules.isBcMod(blockRegistryName.getResourceDomain()))) { - TileEntity entity = world.getTileEntity(data.getPos()); + // @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, Player player, Level world, BlockState blockState, IProbeHitData data) { + ResourceLocation blockRegistryName = BlockUtil.getRegistryName(blockState.getBlock()); + if (blockRegistryName != null && BCModules.isBcMod(blockRegistryName.getNamespace())) { + BlockEntity entity = world.getBlockEntity(data.getPos()); if (entity instanceof IAutoCraft) { this.addAutoCraftInfo(probeInfo, (IAutoCraft) entity); } @@ -74,36 +64,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(Component.translatable("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(Component.translatable("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(Component.translatable("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(Component.translatable("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(Component.translatable("buildcraft.waila.crafting")).item(result); + } else { + IProbeInfo mainInfo = probeInfo.vertical(); + mainInfo.horizontal(mainInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER)).text(Component.translatable("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..40e3604 --- /dev/null +++ b/common/buildcraft/compat/module/waila/AssemblyCraftDataProvider.java @@ -0,0 +1,63 @@ +package buildcraft.compat.module.waila; + +import buildcraft.lib.tile.craft.IAssemblyCraft; +import buildcraft.silicon.BCSilicon; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.phys.Vec2; +import snownee.jade.api.BlockAccessor; +import snownee.jade.api.ITooltip; +import snownee.jade.api.config.IPluginConfig; +import snownee.jade.impl.ui.ItemStackElement; +import snownee.jade.impl.ui.SpacerElement; + +public class AssemblyCraftDataProvider { + static class BodyProvider extends BaseWailaDataProvider.BodyProvider { + @Override + public void getWailaBody(ITooltip currentTip, BlockAccessor accessor, IPluginConfig iPluginConfig) { + BlockEntity tile = accessor.getBlockEntity(); + if (tile instanceof IAssemblyCraft) { +// CompoundTag nbt = accessor.getNBTData(); + CompoundTag nbt = accessor.getServerData(); + if (nbt.contains("recipe_result", Tag.TAG_COMPOUND)) { + ItemStack recipe_result = ItemStack.of(nbt.getCompound("recipe_result")); + if (!recipe_result.isEmpty()) { + currentTip.add(Component.translatable("buildcraft.waila.crafting")); + currentTip.append(ItemStackElement.of(recipe_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 SpacerElement(new Vec2(0, 5))); + return; + } + } + currentTip.add(Component.translatable("buildcraft.waila.no_recipe")); + } +// else { +// currentTip.add(new TextComponent(ChatFormatting.RED + "{wrong tile entity}")); +// } + } + + @Override + public ResourceLocation getUid() { + return ResourceLocation.tryBuild(BCSilicon.MODID, "assembly_client_data"); + } + } + + static class NBTProvider extends BaseWailaDataProvider.NBTProvider { + @Override + public void getNBTData(CompoundTag nbt, BlockAccessor accessor) { + if (accessor.getBlockEntity() instanceof IAssemblyCraft assembly) { + nbt.put("recipe_result", assembly.getAssemblyResult().serializeNBT()); + } + } + + @Override + public ResourceLocation getUid() { + return ResourceLocation.tryBuild(BCSilicon.MODID, "assembly_server_data"); + } + } +} diff --git a/common/buildcraft/compat/module/waila/AutoCraftDataProvider.java b/common/buildcraft/compat/module/waila/AutoCraftDataProvider.java index df1f7c4..449ba5d 100644 --- a/common/buildcraft/compat/module/waila/AutoCraftDataProvider.java +++ b/common/buildcraft/compat/module/waila/AutoCraftDataProvider.java @@ -1,83 +1,87 @@ 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 net.minecraft.nbt.NBTTagList; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.text.TextFormatting; -import net.minecraft.world.World; - -import net.minecraftforge.common.util.Constants; -import net.minecraftforge.fml.common.Optional; - +import buildcraft.compat.CompatUtils; +import buildcraft.factory.BCFactory; import buildcraft.lib.tile.craft.IAutoCraft; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.phys.Vec2; +import snownee.jade.api.BlockAccessor; +import snownee.jade.api.ITooltip; +import snownee.jade.api.config.IPluginConfig; +import snownee.jade.impl.ui.ItemStackElement; +import snownee.jade.impl.ui.SpacerElement; -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(ITooltip currentTip, BlockAccessor accessor, IPluginConfig iPluginConfig) { + BlockEntity tile = accessor.getBlockEntity(); + if (tile instanceof IAutoCraft) { + CompoundTag nbt = accessor.getServerData(); + if (nbt.contains("recipe_result", Tag.TAG_COMPOUND)) { + // Calen: add -> create new line / append -> append at the last line + ItemStack result = ItemStack.of(nbt.getCompound("recipe_result")); + currentTip.add(Component.translatable("buildcraft.waila.crafting")); + currentTip.append(ItemStackElement.of(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 SpacerElement(new Vec2(0, 5))); + if (nbt.contains("recipe_inputs", Tag.TAG_LIST)) { + ListTag list = nbt.getList("recipe_inputs", Tag.TAG_COMPOUND); + currentTip.add(Component.translatable("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) { + CompoundTag compound = list.getCompound(index); + currentTip.append(ItemStackElement.of(ItemStack.of(compound))); + } + currentTip.add(new SpacerElement(new Vec2(0, 5))); } - currentTip.add(inputs.toString()); + } else { + currentTip.add(Component.translatable("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}")); +// } + } + + @Override + public ResourceLocation getUid() { + return ResourceLocation.tryBuild(BCFactory.MODID, "autocraft_client_data"); } - 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(CompoundTag nbt, BlockAccessor accessor) { + if (accessor.getBlockEntity() instanceof IAutoCraft auto) { + ItemStack output = auto.getCurrentRecipeOutput(); + if (!output.isEmpty()) { + nbt.put("recipe_result", output.serializeNBT()); + List stacks = CompatUtils.compactInventory(auto.getInvBlueprint()); + ListTag list = new ListTag(); - 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; + @Override + public ResourceLocation getUid() { + return ResourceLocation.tryBuild(BCFactory.MODID, "autocraft_server_data"); + } } } diff --git a/common/buildcraft/compat/module/waila/BaseWailaDataProvider.java b/common/buildcraft/compat/module/waila/BaseWailaDataProvider.java index 630b8af..019d38c 100644 --- a/common/buildcraft/compat/module/waila/BaseWailaDataProvider.java +++ b/common/buildcraft/compat/module/waila/BaseWailaDataProvider.java @@ -1,57 +1,36 @@ 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 net.minecraft.tileentity.TileEntity; -import net.minecraft.util.math.BlockPos; -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; - -@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; - } - - @Nonnull - @Override - @Optional.Method(modid = WAILA_MOD_ID) - public List getWailaHead(ItemStack itemStack, List currentTip, IWailaDataAccessor accessor, IWailaConfigHandler config) { - return currentTip; - } - - @Nonnull - @Override - @Optional.Method(modid = WAILA_MOD_ID) - public List getWailaBody(ItemStack itemStack, List currentTip, IWailaDataAccessor accessor, IWailaConfigHandler config) { - return currentTip; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import snownee.jade.api.BlockAccessor; +import snownee.jade.api.IBlockComponentProvider; +import snownee.jade.api.IServerDataProvider; +import snownee.jade.api.ITooltip; +import snownee.jade.api.config.IPluginConfig; + +//class BaseWailaDataProvider implements IWailaDataProvider +public interface BaseWailaDataProvider { + + static abstract class BodyProvider implements IBlockComponentProvider { + @Override + public void appendTooltip(ITooltip iTooltip, BlockAccessor blockAccessor, IPluginConfig iPluginConfig) { + getWailaBody(iTooltip, blockAccessor, iPluginConfig); + } + + abstract void getWailaBody(ITooltip iTooltip, BlockAccessor 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 + static abstract class NBTProvider implements IServerDataProvider { + @Override +// public void appendServerData(CompoundTag tag, ServerPlayer player, Level blockAccessor, BlockEntity blockEntity, boolean showDetails) + public void appendServerData(CompoundTag tag, BlockAccessor accessor) { + getNBTData(tag, accessor); + } - @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(CompoundTag tag, ServerPlayer player, Level blockAccessor, BlockEntity blockEntity, boolean showDetails); + abstract void getNBTData(CompoundTag tag, BlockAccessor accessor); } } diff --git a/common/buildcraft/compat/module/waila/HWYLAPlugin.java b/common/buildcraft/compat/module/waila/HWYLAPlugin.java index 2ddff63..4410b1c 100644 --- a/common/buildcraft/compat/module/waila/HWYLAPlugin.java +++ b/common/buildcraft/compat/module/waila/HWYLAPlugin.java @@ -1,49 +1,42 @@ package buildcraft.compat.module.waila; -import static buildcraft.compat.module.waila.HWYLAPlugin.WAILA_MOD_ID; - -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 buildcraft.lib.block.BlockBCTile_Neptune; +import buildcraft.lib.tile.TileBC_Neptune; +import snownee.jade.api.*; @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(IWailaCommonRegistration registrar) { + IServerDataProvider autoCraftNbtProvider = new AutoCraftDataProvider.NBTProvider(); + IServerDataProvider laserTargetNbtProvider = new LaserTargetDataProvider.NBTProvider(); + IServerDataProvider assemblyCraftNbtProvider = new AssemblyCraftDataProvider.NBTProvider(); + IServerDataProvider mjStorageNbtProvider = new MjStorageDataProvider.NBTProvider(); + + registrar.registerBlockDataProvider(autoCraftNbtProvider, TileBC_Neptune.class); + registrar.registerBlockDataProvider(laserTargetNbtProvider, TileBC_Neptune.class); + registrar.registerBlockDataProvider(assemblyCraftNbtProvider, TileBC_Neptune.class); + registrar.registerBlockDataProvider(mjStorageNbtProvider, TileBC_Neptune.class); } - static String getItemStackString(ItemStack stack) { - return getItemStackString(stack, "1"); - } - - private static String 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()) - ); + @Override + public void registerClient(IWailaClientRegistration registrar) { +// IComponentProvider autoCraftBodyProvider = new AutoCraftDataProvider.BodyProvider(); +// IComponentProvider laserTargetBodyProvider = new LaserTargetDataProvider.BodyProvider(); +// IComponentProvider assemblyCraftBodyProvider = new AssemblyCraftDataProvider.BodyProvider(); + IBlockComponentProvider autoCraftBodyProvider = new AutoCraftDataProvider.BodyProvider(); + IBlockComponentProvider laserTargetBodyProvider = new LaserTargetDataProvider.BodyProvider(); + IBlockComponentProvider assemblyCraftBodyProvider = new AssemblyCraftDataProvider.BodyProvider(); + IBlockComponentProvider mjStorageBodyProvider = new MjStorageDataProvider.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); + registrar.registerBlockComponent(autoCraftBodyProvider, BlockBCTile_Neptune.class); + registrar.registerBlockComponent(laserTargetBodyProvider, BlockBCTile_Neptune.class); + registrar.registerBlockComponent(assemblyCraftBodyProvider, BlockBCTile_Neptune.class); + registrar.registerBlockComponent(mjStorageBodyProvider, BlockBCTile_Neptune.class); } } diff --git a/common/buildcraft/compat/module/waila/LaserTargetDataProvider.java b/common/buildcraft/compat/module/waila/LaserTargetDataProvider.java index 426e975..8bcc917 100644 --- a/common/buildcraft/compat/module/waila/LaserTargetDataProvider.java +++ b/common/buildcraft/compat/module/waila/LaserTargetDataProvider.java @@ -1,56 +1,54 @@ 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 net.minecraft.tileentity.TileEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.text.TextFormatting; -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 buildcraft.silicon.BCSilicon; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.entity.BlockEntity; +import snownee.jade.api.BlockAccessor; +import snownee.jade.api.ITooltip; +import snownee.jade.api.config.IPluginConfig; -import mcp.mobius.waila.api.IWailaConfigHandler; -import mcp.mobius.waila.api.IWailaDataAccessor; +abstract class LaserTargetDataProvider { -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"); + static class BodyProvider extends BaseWailaDataProvider.BodyProvider { + @Override + public void getWailaBody(ITooltip currentTip, BlockAccessor accessor, IPluginConfig iPluginConfig) { + BlockEntity tile = accessor.getBlockEntity(); + if (tile instanceof ILaserTarget) { + CompoundTag nbt = accessor.getServerData(); + if (nbt.contains("required_power", Tag.TAG_LONG)) { + long power = nbt.getLong("required_power"); + if (power > 0L) { + currentTip.add(Component.translatable("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); + @Override + public ResourceLocation getUid() { + return ResourceLocation.tryBuild(BCSilicon.MODID, "laser_target_client_data"); + } + } - 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(CompoundTag nbt, BlockAccessor accessor) { + if (accessor.getBlockEntity() instanceof ILaserTarget target) { + nbt.putLong("required_power", target.getRequiredLaserPower()); + } } - return nbt; + @Override + public ResourceLocation getUid() { + return ResourceLocation.tryBuild(BCSilicon.MODID, "laser_target_server_data"); + } } } diff --git a/common/buildcraft/compat/module/waila/MjStorageDataProvider.java b/common/buildcraft/compat/module/waila/MjStorageDataProvider.java new file mode 100644 index 0000000..da587d1 --- /dev/null +++ b/common/buildcraft/compat/module/waila/MjStorageDataProvider.java @@ -0,0 +1,64 @@ +package buildcraft.compat.module.waila; + +import buildcraft.api.mj.MjAPI; +import buildcraft.core.BCCore; +import buildcraft.lib.tile.TileBC_Neptune; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.DyeColor; +import snownee.jade.api.BlockAccessor; +import snownee.jade.api.ITooltip; +import snownee.jade.api.config.IPluginConfig; +import snownee.jade.api.ui.BoxStyle; +import snownee.jade.api.ui.IProgressStyle; +import snownee.jade.impl.ui.ProgressElement; +import snownee.jade.impl.ui.ProgressStyle; + +public class MjStorageDataProvider { + static class BodyProvider extends BaseWailaDataProvider.BodyProvider { + private static final IProgressStyle PROGRESS_STYLE = new ProgressStyle() + .color(-15731468, -16721961) + .textColor(DyeColor.WHITE.getTextColor()); + + @Override + public void getWailaBody(ITooltip currentTip, BlockAccessor accessor, IPluginConfig iPluginConfig) { + if (accessor.getBlockEntity() instanceof TileBC_Neptune tileBC) { + tileBC.getCapability(MjAPI.CAP_READABLE).ifPresent(mjReadable -> { + CompoundTag nbt = accessor.getServerData(); + if (nbt.contains("mj_storage", Tag.TAG_COMPOUND)) { + CompoundTag mj_storage_Tag = nbt.getCompound("mj_storage"); + long mj_capability = mj_storage_Tag.getLong("mj_capability"); + long mj_stored = mj_storage_Tag.getLong("mj_stored"); + currentTip.add(new ProgressElement((float) (((double) mj_stored) / ((double) mj_capability)), Component.literal(mj_stored + " MJ/" + mj_capability + "MJ"), PROGRESS_STYLE, BoxStyle.DEFAULT, false)); + } + }); + } + } + + @Override + public ResourceLocation getUid() { + return ResourceLocation.tryBuild(BCCore.MODID, "mj_storage_client_data"); + } + } + + static class NBTProvider extends BaseWailaDataProvider.NBTProvider { + @Override + public void getNBTData(CompoundTag nbt, BlockAccessor accessor) { + if (accessor.getBlockEntity() instanceof TileBC_Neptune tileBC) { + tileBC.getCapability(MjAPI.CAP_READABLE).ifPresent(mjReadable -> { + CompoundTag mj_storage_Tag = new CompoundTag(); + mj_storage_Tag.putLong("mj_capability", mjReadable.getCapacity() / MjAPI.MJ); + mj_storage_Tag.putLong("mj_stored", mjReadable.getStored() / MjAPI.MJ); + nbt.put("mj_storage", mj_storage_Tag); + }); + } + } + + @Override + public ResourceLocation getUid() { + return ResourceLocation.tryBuild(BCCore.MODID, "mj_storage_server_data"); + } + } +} 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..7897365 100644 --- a/common/buildcraft/compat/network/IGuiCreator.java +++ b/common/buildcraft/compat/network/IGuiCreator.java @@ -1,25 +1,22 @@ 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.screens.inventory.AbstractContainerScreen; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +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); + AbstractContainerScreen getClientGuiElement(int var1, Player 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); + AbstractContainerMenu getServerGuiElement(int var1, Player var2); } diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..aa2c4cc --- /dev/null +++ b/gradle.properties @@ -0,0 +1,38 @@ +org.gradle.jvmargs=-Xmx3G +org.gradle.daemon=false + + +minecraft_version=1.20.1 +minecraft_version_range=[1.20.1,1.20.2) +forge_version=47.3.12 +# The Forge version range can use any version of Forge as bounds or match the loader version range +forge_version_range=[47,) +# The loader version range can only use the major version of Forge/FML as bounds +loader_version_range=[47,) +# The mapping channel to use for mappings. +# The default set of supported mapping channels are ["official", "snapshot", "snapshot_nodoc", "stable", "stable_nodoc"]. +# Additional mapping channels can be registered through the "channelProviders" extension in a Gradle plugin. +# +# | Channel | Version | | +# |-----------|----------------------|--------------------------------------------------------------------------------| +# | official | MCVersion | Official field/method names from Mojang mapping files | +# | parchment | YYYY.MM.DD-MCVersion | Open community-sourced parameter names and javadocs layered on top of official | +# +# You must be aware of the Mojang license when using the 'official' or 'parchment' mappings. +# See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md +# +# Parchment is an unofficial project maintained by ParchmentMC, separate from Minecraft Forge. +# Additional setup is needed to use their mappings, see https://parchmentmc.org/docs/getting-started +mapping_channel=official +# The mapping version to query from the mapping channel. +# This must match the format required by the mapping channel. +mapping_version=1.20.1 + + +mod_id=buildcraft +mod_name=BuildCraft +mod_license=Minecraft Mod Public License +mod_version=7.99.24.9 +mod_group_id=com.mod-buildcraft +mod_authors=SpaceToad, BuildCraft Team +mod_description=Extending Minecraft with pipes, auto-crafting, quarries, engines and much more! diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index ca78035ef0501d802d4fc55381ef2d5c3ce0ec6e..c1962a79e29d3e0ab67b14947c167a862655af9b 100644 GIT binary patch literal 62076 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 literal 53556 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�H$uJM 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 \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum -warn ( ) { +warn () { echo "$*" -} +} >&2 -die ( ) { +die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -81,7 +129,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -89,76 +137,109 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 832fdb6..93e3f59 100755 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,4 +1,20 @@ -@if "%DEBUG%" == "" @echo off +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -9,19 +25,23 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -35,7 +55,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -45,44 +65,26 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/mod_info/META-INF/mods.toml b/mod_info/META-INF/mods.toml new file mode 100644 index 0000000..a055f53 --- /dev/null +++ b/mod_info/META-INF/mods.toml @@ -0,0 +1,151 @@ +modLoader="javafml" +loaderVersion="[47,)" +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="[47,)" + ordering="NONE" + side="BOTH" +[[dependencies.buildcraftcore]] + modId="minecraft" + mandatory=true + versionRange="[1.20,1.20.2)" + 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" diff --git a/resources/META-INF/mods.toml_ b/resources/META-INF/mods.toml_ new file mode 100644 index 0000000..9864995 --- /dev/null +++ b/resources/META-INF/mods.toml_ @@ -0,0 +1,32 @@ +modLoader="javafml" +loaderVersion="[32,)" +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="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.buildcraftcompat]] + modId="buildcraftcore" + mandatory=true + versionRange="[0.0.0,)" + ordering="AFTER" + side="BOTH" diff --git a/resources/assets/buildcraftcompat/lang/de_DE.lang b/resources/assets/buildcraftcompat/lang/de_DE.lang deleted file mode 100644 index 03ffea5..0000000 --- a/resources/assets/buildcraftcompat/lang/de_DE.lang +++ /dev/null @@ -1,20 +0,0 @@ -#################### -# APIARIST'S PIPE -#################### - -item.buildcraftPipe.pipeitemspropolis.name=Bienenrohr - -for.gui.pipe.filter.anything=Alles -for.gui.pipe.filter.bee=Alle Bienen -for.gui.pipe.filter.cave=Höhlenbewohner -for.gui.pipe.filter.closed=Geschlossen -for.gui.pipe.filter.drone=Dronen -for.gui.pipe.filter.flyer=Starke Flieger -for.gui.pipe.filter.item=Gegenstände -for.gui.pipe.filter.nocturnal=Nachtaktive -for.gui.pipe.filter.princess=Prinzessinnen -for.gui.pipe.filter.pure_breed=Reinrassige -for.gui.pipe.filter.pure_cave=Reinrassige Höhlenbewohner -for.gui.pipe.filter.pure_flyer=Reinrassig starke Flieger -for.gui.pipe.filter.pure_nocturnal=Reinrassig nachtaktive -for.gui.pipe.filter.queen=Königinnen diff --git a/resources/assets/buildcraftcompat/lang/de_de.json b/resources/assets/buildcraftcompat/lang/de_de.json new file mode 100644 index 0000000..728942c --- /dev/null +++ b/resources/assets/buildcraftcompat/lang/de_de.json @@ -0,0 +1,24 @@ +{ + //################### + // APIARIST'S PIPE + //################### + + "item.buildcraftPipe.pipeitemspropolis.name": "Bienenrohr", + + "for.gui.pipe.filter.anything": "Alles", + "for.gui.pipe.filter.bee": "Alle Bienen", + "for.gui.pipe.filter.cave": "Höhlenbewohner", + "for.gui.pipe.filter.closed": "Geschlossen", + "for.gui.pipe.filter.drone": "Dronen", + "for.gui.pipe.filter.flyer": "Starke Flieger", + "for.gui.pipe.filter.item": "Gegenstände", + "for.gui.pipe.filter.nocturnal": "Nachtaktive", + "for.gui.pipe.filter.princess": "Prinzessinnen", + "for.gui.pipe.filter.pure_breed": "Reinrassige", + "for.gui.pipe.filter.pure_cave": "Reinrassige Höhlenbewohner", + "for.gui.pipe.filter.pure_flyer": "Reinrassig starke Flieger", + "for.gui.pipe.filter.pure_nocturnal": "Reinrassig nachtaktive", + "for.gui.pipe.filter.queen": "Königinnen", + + "null": "=w=" +} diff --git a/resources/assets/buildcraftcompat/lang/en_US.lang b/resources/assets/buildcraftcompat/lang/en_US.lang deleted file mode 100644 index 3975239..0000000 --- a/resources/assets/buildcraftcompat/lang/en_US.lang +++ /dev/null @@ -1,25 +0,0 @@ -#################### -# APIARIST'S PIPE -#################### - -item.buildcraftPipe.pipeitemspropolis.name=Apiarist's Pipe - -for.gui.pipe.filter.anything=Anything -for.gui.pipe.filter.bee=Any Bees -for.gui.pipe.filter.cave=Cave-Dwellers -for.gui.pipe.filter.closed=Closed -for.gui.pipe.filter.drone=Drones -for.gui.pipe.filter.flyer=Strong Flyers -for.gui.pipe.filter.item=Items -for.gui.pipe.filter.natural=Natural Origin -for.gui.pipe.filter.nocturnal=Nocturnal Bees -for.gui.pipe.filter.princess=Princesses -for.gui.pipe.filter.pure_breed=Pure-Bred Bees -for.gui.pipe.filter.pure_cave=Pure Cave-Dwellers -for.gui.pipe.filter.pure_flyer=Pure Flyers -for.gui.pipe.filter.pure_nocturnal=Pure Nocturnal Bees -for.gui.pipe.filter.queen=Queen - -gate.trigger.mfr.backstuffed=Has Drops -gate.trigger.mfr.conreversed=Conveyor Reversed -gate.trigger.mfr.conrunning=Conveyor Running \ No newline at end of file diff --git a/resources/assets/buildcraftcompat/lang/en_us.json b/resources/assets/buildcraftcompat/lang/en_us.json new file mode 100644 index 0000000..24d3e4d --- /dev/null +++ b/resources/assets/buildcraftcompat/lang/en_us.json @@ -0,0 +1,65 @@ +{ + //################### + // APIARIST'S PIPE + //################### + + "item.buildcraftPipe.pipeitemspropolis.name": "Apiarist's Pipe", + + "for.gui.pipe.filter.anything": "Anything", + "for.gui.pipe.filter.bee": "Any Bees", + "for.gui.pipe.filter.cave": "Cave-Dwellers", + "for.gui.pipe.filter.closed": "Closed", + "for.gui.pipe.filter.drone": "Drones", + "for.gui.pipe.filter.flyer": "Strong Flyers", + "for.gui.pipe.filter.item": "Items", + "for.gui.pipe.filter.natural": "Natural Origin", + "for.gui.pipe.filter.nocturnal": "Nocturnal Bees", + "for.gui.pipe.filter.princess": "Princesses", + "for.gui.pipe.filter.pure_breed": "Pure-Bred Bees", + "for.gui.pipe.filter.pure_cave": "Pure Cave-Dwellers", + "for.gui.pipe.filter.pure_flyer": "Pure Flyers", + "for.gui.pipe.filter.pure_nocturnal": "Pure Nocturnal Bees", + "for.gui.pipe.filter.queen": "Queen", + + "gate.trigger.mfr.backstuffed": "Has Drops", + "gate.trigger.mfr.conreversed": "Conveyor Reversed", + "gate.trigger.mfr.conrunning": "Conveyor Running", + + // Calen 1.18.2 + // JEI + "buildcraft.jei.title.heatable_fluids": "Heatable Fluids", + "buildcraft.jei.title.coolable_fluids": "Coolable Fluids", + "buildcraft.jei.title.distillable_fluids": "Distillable Fluids", + "buildcraft.jei.title.combustion_engine_fuels": "Combustion Engine Fuels", + "buildcraft.jei.title.combustion_engine_fuels.burn_time": "Burns for %ds", + "buildcraft.jei.title.combustion_engine_fuels.burn_speed": " at %s MJ/t", + "buildcraft.jei.title.combustion_engine_fuels.burn_total": " total %s MJ", + + // REI + "buildcraft.rei.title.heatable_fluids": "Heatable Fluids", + "buildcraft.rei.title.coolable_fluids": "Coolable Fluids", + "buildcraft.rei.title.distillable_fluids": "Distillable Fluids", + "buildcraft.rei.title.combustion_engine_fuels": "Combustion Engine Fuels", + "buildcraft.rei.title.combustion_engine_fuels.burn_time": "Burns for %ds", + "buildcraft.rei.title.combustion_engine_fuels.burn_speed": " at %s MJ/t", + "buildcraft.rei.title.combustion_engine_fuels.burn_total": " total %s MJ", + + // Waila + "buildcraft.waila.crafting": "§fMaking: ", + "buildcraft.waila.no_recipe": "§7No recipe", + "buildcraft.waila.crafting_from": "§fFrom: ", + "buildcraft.waila.waiting_for_laser": "§fWaiting from laser: §b%s MJ", + "config.jade.plugin_buildcraftsilicon.laser_target_client_data": "Laser Target", + "config.jade.plugin_buildcraftsilicon.laser_target_server_data": "Laser Target", + "config.jade.plugin_buildcraftfactory.autocraft_client_data": "Autocraft", + "config.jade.plugin_buildcraftfactory.autocraft_server_data": "Autocraft", + "config.jade.plugin_buildcraftsilicon.assembly_client_data": "Assembly", + "config.jade.plugin_buildcraftsilicon.assembly_server_data": "Assembly", + "config.jade.plugin_buildcraftcore.mj_storage_client_data": "MJ Storage", + "config.jade.plugin_buildcraftcore.mj_storage_server_data": "MJ Storage", + + // Calen FE compat + "tile.power_convertor.name": "Power Convertor", + + "null": "=w=" +} diff --git a/resources/assets/buildcraftcompat/lang/fr_FR.lang b/resources/assets/buildcraftcompat/lang/fr_FR.lang deleted file mode 100644 index 02f01f3..0000000 --- a/resources/assets/buildcraftcompat/lang/fr_FR.lang +++ /dev/null @@ -1,20 +0,0 @@ -#################### -# APIARIST'S PIPE -#################### - -item.buildcraftPipe.pipeitemspropolis.name=Tuyau de transport d'apiculteur - -for.gui.pipe.filter.anything=Tout -for.gui.pipe.filter.bee=Toutes abeilles -for.gui.pipe.filter.cave=De cave -for.gui.pipe.filter.closed=Rien -for.gui.pipe.filter.drone=Ouvrières -for.gui.pipe.filter.flyer=Les volantes -for.gui.pipe.filter.item=Éléments -for.gui.pipe.filter.nocturnal=Les noctures -for.gui.pipe.filter.princess=Princesses -for.gui.pipe.filter.pure_breed=Pures races -for.gui.pipe.filter.pure_cave=De cave pures -for.gui.pipe.filter.pure_flyer=Volantes pures -for.gui.pipe.filter.pure_nocturnal=Nocturne pures -for.gui.pipe.filter.queen=Reines diff --git a/resources/assets/buildcraftcompat/lang/fr_fr.json b/resources/assets/buildcraftcompat/lang/fr_fr.json new file mode 100644 index 0000000..d35b127 --- /dev/null +++ b/resources/assets/buildcraftcompat/lang/fr_fr.json @@ -0,0 +1,24 @@ +{ + //################### + // APIARIST'S PIPE + //################### + + "item.buildcraftPipe.pipeitemspropolis.name": "Tuyau de transport d'apiculteur", + + "for.gui.pipe.filter.anything": "Tout", + "for.gui.pipe.filter.bee": "Toutes abeilles", + "for.gui.pipe.filter.cave": "De cave", + "for.gui.pipe.filter.closed": "Rien", + "for.gui.pipe.filter.drone": "Ouvrières", + "for.gui.pipe.filter.flyer": "Les volantes", + "for.gui.pipe.filter.item": "Éléments", + "for.gui.pipe.filter.nocturnal": "Les noctures", + "for.gui.pipe.filter.princess": "Princesses", + "for.gui.pipe.filter.pure_breed": "Pures races", + "for.gui.pipe.filter.pure_cave": "De cave pures", + "for.gui.pipe.filter.pure_flyer": "Volantes pures", + "for.gui.pipe.filter.pure_nocturnal": "Nocturne pures", + "for.gui.pipe.filter.queen": "Reines", + + "null": "=w=" +} diff --git a/resources/assets/buildcraftcompat/lang/ko_KR.lang b/resources/assets/buildcraftcompat/lang/ko_KR.lang deleted file mode 100644 index bdcfa70..0000000 --- a/resources/assets/buildcraftcompat/lang/ko_KR.lang +++ /dev/null @@ -1,20 +0,0 @@ -#################### -# APIARIST'S PIPE -#################### - -item.buildcraftPipe.pipeitemspropolis.name=양봉업자의 파이프 - -for.gui.pipe.filter.anything=모든 아이템과 벌을 통과 -for.gui.pipe.filter.bee=모든 벌들 -for.gui.pipe.filter.cave=동굴 속에서도 작업 가능 -for.gui.pipe.filter.closed=아이템을 받지 않음 -for.gui.pipe.filter.drone=일벌 -for.gui.pipe.filter.flyer=우천시에도 작업 가능 -for.gui.pipe.filter.item=아이템만 -for.gui.pipe.filter.nocturnal=야행성 벌 -for.gui.pipe.filter.princess=공주벌 -for.gui.pipe.filter.pure_breed=공주벌 -for.gui.pipe.filter.pure_cave=동굴 속에서도 작업 가능한 순종 벌 -for.gui.pipe.filter.pure_flyer=우천시에도 작업 가능한 순종 벌 -for.gui.pipe.filter.pure_nocturnal=순종 야행성 벌 -for.gui.pipe.filter.queen=여왕벌 diff --git a/resources/assets/buildcraftcompat/lang/ko_kr.json b/resources/assets/buildcraftcompat/lang/ko_kr.json new file mode 100644 index 0000000..aba0c09 --- /dev/null +++ b/resources/assets/buildcraftcompat/lang/ko_kr.json @@ -0,0 +1,24 @@ +{ + //################### + // APIARIST'S PIPE + //################### + + "item.buildcraftPipe.pipeitemspropolis.name": "양봉업자의 파이프", + + "for.gui.pipe.filter.anything": "모든 아이템과 벌을 통과", + "for.gui.pipe.filter.bee": "모든 벌들", + "for.gui.pipe.filter.cave": "동굴 속에서도 작업 가능", + "for.gui.pipe.filter.closed": "아이템을 받지 않음", + "for.gui.pipe.filter.drone": "일벌", + "for.gui.pipe.filter.flyer": "우천시에도 작업 가능", + "for.gui.pipe.filter.item": "아이템만", + "for.gui.pipe.filter.nocturnal": "야행성 벌", + "for.gui.pipe.filter.princess": "공주벌", + "for.gui.pipe.filter.pure_breed": "공주벌", + "for.gui.pipe.filter.pure_cave": "동굴 속에서도 작업 가능한 순종 벌", + "for.gui.pipe.filter.pure_flyer": "우천시에도 작업 가능한 순종 벌", + "for.gui.pipe.filter.pure_nocturnal": "순종 야행성 벌", + "for.gui.pipe.filter.queen": "여왕벌", + + "null": "=w=" +} diff --git a/resources/assets/buildcraftcompat/lang/pt_BR.lang b/resources/assets/buildcraftcompat/lang/pt_BR.lang deleted file mode 100644 index 35da29d..0000000 --- a/resources/assets/buildcraftcompat/lang/pt_BR.lang +++ /dev/null @@ -1,20 +0,0 @@ -#################### -# APIARIST'S PIPE -#################### - -item.buildcraftPipe.pipeitemspropolis.name=Tubo do Apicultor - -for.gui.pipe.filter.anything=Nada -for.gui.pipe.filter.bee=Quaisquer Abelhas -for.gui.pipe.filter.cave=Habitante de Cavernas -for.gui.pipe.filter.closed=Fechado -for.gui.pipe.filter.drone=Zangões -for.gui.pipe.filter.flyer=Insetos Fortes -for.gui.pipe.filter.item=Ítens -for.gui.pipe.filter.nocturnal=Abelhas Noturnas -for.gui.pipe.filter.princess=Princesas -for.gui.pipe.filter.pure_breed=Abelhas de Raça Pura -for.gui.pipe.filter.pure_cave=Puras Habitantes das Cavernas -for.gui.pipe.filter.pure_flyer=Insetos Puros -for.gui.pipe.filter.pure_nocturnal=Abelhas Noturnas Puras -for.gui.pipe.filter.queen=Rainha diff --git a/resources/assets/buildcraftcompat/lang/pt_br.json b/resources/assets/buildcraftcompat/lang/pt_br.json new file mode 100644 index 0000000..8a5185f --- /dev/null +++ b/resources/assets/buildcraftcompat/lang/pt_br.json @@ -0,0 +1,24 @@ +{ + //################### + // APIARIST'S PIPE + //################### + + "item.buildcraftPipe.pipeitemspropolis.name": "Tubo do Apicultor", + + "for.gui.pipe.filter.anything": "Nada", + "for.gui.pipe.filter.bee": "Quaisquer Abelhas", + "for.gui.pipe.filter.cave": "Habitante de Cavernas", + "for.gui.pipe.filter.closed": "Fechado", + "for.gui.pipe.filter.drone": "Zangões", + "for.gui.pipe.filter.flyer": "Insetos Fortes", + "for.gui.pipe.filter.item": "Ítens", + "for.gui.pipe.filter.nocturnal": "Abelhas Noturnas", + "for.gui.pipe.filter.princess": "Princesas", + "for.gui.pipe.filter.pure_breed": "Abelhas de Raça Pura", + "for.gui.pipe.filter.pure_cave": "Puras Habitantes das Cavernas", + "for.gui.pipe.filter.pure_flyer": "Insetos Puros", + "for.gui.pipe.filter.pure_nocturnal": "Abelhas Noturnas Puras", + "for.gui.pipe.filter.queen": "Rainha", + + "null": "=w=" +} diff --git a/resources/assets/buildcraftcompat/lang/ru_RU.lang b/resources/assets/buildcraftcompat/lang/ru_RU.lang deleted file mode 100644 index 4d41e5a..0000000 --- a/resources/assets/buildcraftcompat/lang/ru_RU.lang +++ /dev/null @@ -1,25 +0,0 @@ -#################### -# APIARIST'S PIPE -#################### - -item.buildcraftPipe.pipeitemspropolis.name=Труба пчеловода - -for.gui.pipe.filter.anything=Всё -for.gui.pipe.filter.bee=Любые пчелы -for.gui.pipe.filter.cave=Пещерные -for.gui.pipe.filter.closed=Закрыт -for.gui.pipe.filter.drone=Трутни -for.gui.pipe.filter.flyer=Летуны -for.gui.pipe.filter.item=Предметы -for.gui.pipe.filter.natural=Естественного происх. -for.gui.pipe.filter.nocturnal=Ночные -for.gui.pipe.filter.princess=Принцессы -for.gui.pipe.filter.pure_breed=Чистопородные -for.gui.pipe.filter.pure_cave=Породистые пещерные -for.gui.pipe.filter.pure_flyer=Породистые летуны -for.gui.pipe.filter.pure_nocturnal=Породистые ночные -for.gui.pipe.filter.queen=Матки - -gate.trigger.mfr.backstuffed=Есть предметы -gate.trigger.mfr.conreversed=Конвейер реверсирован -gate.trigger.mfr.conrunning=Конвейер работает \ No newline at end of file diff --git a/resources/assets/buildcraftcompat/lang/ru_ru.json b/resources/assets/buildcraftcompat/lang/ru_ru.json new file mode 100644 index 0000000..1be6465 --- /dev/null +++ b/resources/assets/buildcraftcompat/lang/ru_ru.json @@ -0,0 +1,29 @@ +{ + //################### + // APIARIST'S PIPE + //################### + + "item.buildcraftPipe.pipeitemspropolis.name": "Труба пчеловода", + + "for.gui.pipe.filter.anything": "Всё", + "for.gui.pipe.filter.bee": "Любые пчелы", + "for.gui.pipe.filter.cave": "Пещерные", + "for.gui.pipe.filter.closed": "Закрыт", + "for.gui.pipe.filter.drone": "Трутни", + "for.gui.pipe.filter.flyer": "Летуны", + "for.gui.pipe.filter.item": "Предметы", + "for.gui.pipe.filter.natural": "Естественного происх.", + "for.gui.pipe.filter.nocturnal": "Ночные", + "for.gui.pipe.filter.princess": "Принцессы", + "for.gui.pipe.filter.pure_breed": "Чистопородные", + "for.gui.pipe.filter.pure_cave": "Породистые пещерные", + "for.gui.pipe.filter.pure_flyer": "Породистые летуны", + "for.gui.pipe.filter.pure_nocturnal": "Породистые ночные", + "for.gui.pipe.filter.queen": "Матки", + + "gate.trigger.mfr.backstuffed": "Есть предметы", + "gate.trigger.mfr.conreversed": "Конвейер реверсирован", + "gate.trigger.mfr.conrunning": "Конвейер работает", + + "null": "=w=" +} diff --git a/resources/assets/buildcraftcompat/lang/uk_UA.lang b/resources/assets/buildcraftcompat/lang/uk_UA.lang deleted file mode 100644 index 711c823..0000000 --- a/resources/assets/buildcraftcompat/lang/uk_UA.lang +++ /dev/null @@ -1,20 +0,0 @@ -#################### -# APIARIST'S PIPE -#################### - -item.buildcraftPipe.pipeitemspropolis.name=Труба пчеловода - -for.gui.pipe.filter.anything=Всё -for.gui.pipe.filter.bee=Любые пчелы -for.gui.pipe.filter.cave=Пещерные -for.gui.pipe.filter.closed=Закрыт -for.gui.pipe.filter.drone=Трутни -for.gui.pipe.filter.flyer=Летуны -for.gui.pipe.filter.item=Предметы -for.gui.pipe.filter.nocturnal=Ночные -for.gui.pipe.filter.princess=Принцессы -for.gui.pipe.filter.pure_breed=Чистопородные -for.gui.pipe.filter.pure_cave=Породистые пещерные -for.gui.pipe.filter.pure_flyer=Породистые летуны -for.gui.pipe.filter.pure_nocturnal=Породистые ночные -for.gui.pipe.filter.queen=Королевы diff --git a/resources/assets/buildcraftcompat/lang/uk_ua.json b/resources/assets/buildcraftcompat/lang/uk_ua.json new file mode 100644 index 0000000..da44267 --- /dev/null +++ b/resources/assets/buildcraftcompat/lang/uk_ua.json @@ -0,0 +1,24 @@ +{ + //################### + // APIARIST'S PIPE + //################### + + "item.buildcraftPipe.pipeitemspropolis.name": "Труба пчеловода", + + "for.gui.pipe.filter.anything": "Всё", + "for.gui.pipe.filter.bee": "Любые пчелы", + "for.gui.pipe.filter.cave": "Пещерные", + "for.gui.pipe.filter.closed": "Закрыт", + "for.gui.pipe.filter.drone": "Трутни", + "for.gui.pipe.filter.flyer": "Летуны", + "for.gui.pipe.filter.item": "Предметы", + "for.gui.pipe.filter.nocturnal": "Ночные", + "for.gui.pipe.filter.princess": "Принцессы", + "for.gui.pipe.filter.pure_breed": "Чистопородные", + "for.gui.pipe.filter.pure_cave": "Породистые пещерные", + "for.gui.pipe.filter.pure_flyer": "Породистые летуны", + "for.gui.pipe.filter.pure_nocturnal": "Породистые ночные", + "for.gui.pipe.filter.queen": "Королевы", + + "null": "=w=" +} diff --git a/resources/assets/buildcraftcompat/lang/zh_CN.lang b/resources/assets/buildcraftcompat/lang/zh_CN.lang deleted file mode 100644 index e9f5aff..0000000 --- a/resources/assets/buildcraftcompat/lang/zh_CN.lang +++ /dev/null @@ -1,20 +0,0 @@ -#################### -# APIARIST'S PIPE -#################### - -item.buildcraftPipe.pipeitemspropolis.name=养蜂员管道 - -for.gui.pipe.filter.anything=任意物品 -for.gui.pipe.filter.bee=任意蜜蜂 -for.gui.pipe.filter.cave=穴居蜂 -for.gui.pipe.filter.closed=已关闭 -for.gui.pipe.filter.drone=雄蜂 -for.gui.pipe.filter.flyer=强壮飞蜂 -for.gui.pipe.filter.item=物品 -for.gui.pipe.filter.nocturnal=夜行蜜蜂 -for.gui.pipe.filter.princess=公主蜂 -for.gui.pipe.filter.pure_breed=纯种蜜蜂 -for.gui.pipe.filter.pure_cave=纯种穴居蜂 -for.gui.pipe.filter.pure_flyer=纯种飞蜂 -for.gui.pipe.filter.pure_nocturnal=纯种夜行蜜蜂 -for.gui.pipe.filter.queen=蜂后 diff --git a/resources/assets/buildcraftcompat/lang/zh_cn.json b/resources/assets/buildcraftcompat/lang/zh_cn.json new file mode 100644 index 0000000..11755c0 --- /dev/null +++ b/resources/assets/buildcraftcompat/lang/zh_cn.json @@ -0,0 +1,60 @@ +{ + //################### + // APIARIST'S PIPE + //################### + + "item.buildcraftPipe.pipeitemspropolis.name": "养蜂员管道", + + "for.gui.pipe.filter.anything": "任意物品", + "for.gui.pipe.filter.bee": "任意蜜蜂", + "for.gui.pipe.filter.cave": "穴居蜂", + "for.gui.pipe.filter.closed": "已关闭", + "for.gui.pipe.filter.drone": "雄蜂", + "for.gui.pipe.filter.flyer": "强壮飞蜂", + "for.gui.pipe.filter.item": "物品", + "for.gui.pipe.filter.nocturnal": "夜行蜜蜂", + "for.gui.pipe.filter.princess": "公主蜂", + "for.gui.pipe.filter.pure_breed": "纯种蜜蜂", + "for.gui.pipe.filter.pure_cave": "纯种穴居蜂", + "for.gui.pipe.filter.pure_flyer": "纯种飞蜂", + "for.gui.pipe.filter.pure_nocturnal": "纯种夜行蜜蜂", + "for.gui.pipe.filter.queen": "蜂后", + + // Calen 1.18.2 + // JEI + "buildcraft.jei.title.heatable_fluids": "加热流体", + "buildcraft.jei.title.coolable_fluids": "冷却流体", + "buildcraft.jei.title.distillable_fluids": "蒸馏", + "buildcraft.jei.title.combustion_engine_fuels": "燃油引擎燃料", + "buildcraft.jei.title.combustion_engine_fuels.burn_time": "燃烧时间 %ds", + "buildcraft.jei.title.combustion_engine_fuels.burn_speed": " 产能速率 %s MJ/t", + "buildcraft.jei.title.combustion_engine_fuels.burn_total": " 产能总计 %s MJ", + + // REI + "buildcraft.rei.title.heatable_fluids": "加热流体", + "buildcraft.rei.title.coolable_fluids": "冷却流体", + "buildcraft.rei.title.distillable_fluids": "蒸馏", + "buildcraft.rei.title.combustion_engine_fuels": "燃油引擎燃料", + "buildcraft.rei.title.combustion_engine_fuels.burn_time": "燃烧时间 %ds", + "buildcraft.rei.title.combustion_engine_fuels.burn_speed": " 产能速率 %s MJ/t", + "buildcraft.rei.title.combustion_engine_fuels.burn_total": " 产能总计 %s MJ", + + // Waila + "buildcraft.waila.crafting": "§f正在合成: ", + "buildcraft.waila.no_recipe": "§7当前没有配方正在合成", + "buildcraft.waila.crafting_from": "§f使用: ", + "buildcraft.waila.waiting_for_laser": "§f还需要能量: §b%s MJ", + "config.jade.plugin_buildcraftsilicon.laser_target_client_data": "镭射器目标", + "config.jade.plugin_buildcraftsilicon.laser_target_server_data": "镭射器目标", + "config.jade.plugin_buildcraftfactory.autocraft_client_data": "自动合成台", + "config.jade.plugin_buildcraftfactory.autocraft_server_data": "自动合成台", + "config.jade.plugin_buildcraftsilicon.assembly_client_data": "装配台", + "config.jade.plugin_buildcraftsilicon.assembly_server_data": "装配台", + "config.jade.plugin_buildcraftcore.mj_storage_client_data": "MJ存储", + "config.jade.plugin_buildcraftcore.mj_storage_server_data": "MJ存储", + + // Calen FE compat + "tile.power_convertor.name": "能源转换器", + + "null": "=w=" +} diff --git a/resources/mcmod.info b/resources/mcmod.info deleted file mode 100644 index 4b57663..0000000 --- a/resources/mcmod.info +++ /dev/null @@ -1,16 +0,0 @@ -[{ - "modid": "buildcraftcompat", - "name": "BuildCraft Compat", - "version": "$version", - "mcversion": "$mcversion", - "description": "Compatibility add-on for BuildCraft", - "credits": "Created by asie", - "url": "http://www.mod-buildcraft.com/", - "updateUrl": "", - "authorList": [ "BuildCraft Team" ], - "parent":"buildcraftcore", - "screenshots": [], - "dependencies": [ - "mod_MinecraftForge" - ] -}] diff --git a/settings.gradle b/settings.gradle index 9279d42..d05889e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,15 @@ +pluginManagement { + repositories { + gradlePluginPortal() + maven { + name = 'MinecraftForge' + url = 'https://maven.minecraftforge.net/' + } + } +} + +plugins { + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0' +} include 'BuildCraft' include 'BuildCraft:sub_projects:expression' From 447bcfc556c0b199a0b5f8e3828afa5e5cef94bd Mon Sep 17 00:00:00 2001 From: CalenXwX Date: Wed, 18 Dec 2024 01:56:39 +0800 Subject: [PATCH 2/9] Updated gitsubmodule --- BuildCraft | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BuildCraft b/BuildCraft index 656b0a0..db5ac5e 160000 --- a/BuildCraft +++ b/BuildCraft @@ -1 +1 @@ -Subproject commit 656b0a00a04bf61ebd9f39f6c3e44eac2818b1ec +Subproject commit db5ac5eca22b3d86fcae3f150ad405523639d01f From d3eae09d29595c8c0acbc24abae761b4c8bc1969 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sat, 21 Dec 2024 21:47:44 -0500 Subject: [PATCH 3/9] Fix JEI plugin taking a long time to initialize --- common/buildcraft/compat/module/jei/BCPluginJEI.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/common/buildcraft/compat/module/jei/BCPluginJEI.java b/common/buildcraft/compat/module/jei/BCPluginJEI.java index 74ad674..e549693 100644 --- a/common/buildcraft/compat/module/jei/BCPluginJEI.java +++ b/common/buildcraft/compat/module/jei/BCPluginJEI.java @@ -45,6 +45,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraftforge.fml.ModList; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -222,13 +223,12 @@ public void onRuntimeAvailable(IJeiRuntime jeiRuntime) { BCPluginJEI.jeiRuntime = jeiRuntime; // TODO if disable colored pipes + List itemsToRemove = new ArrayList<>(); Arrays.stream(DyeColor.values()).forEach( color -> PipeRegistry.INSTANCE.getAllRegisteredPipes().forEach( - def -> jeiRuntime.getIngredientManager().removeIngredientsAtRuntime( - VanillaTypes.ITEM_STACK, - List.of(new ItemStack((Item) PipeRegistry.INSTANCE.getItemForPipe(def, color))) - ) + def -> itemsToRemove.add(new ItemStack((Item) PipeRegistry.INSTANCE.getItemForPipe(def, color))) ) ); + jeiRuntime.getIngredientManager().removeIngredientsAtRuntime(VanillaTypes.ITEM_STACK, itemsToRemove); } } From d8cfbe39e5f8eea268b3569ff390f611b24ab654 Mon Sep 17 00:00:00 2001 From: CalenXwX Date: Mon, 23 Dec 2024 01:38:41 +0800 Subject: [PATCH 4/9] Removed trove4j & added GUI phantom slots dragging for JEI&REI --- BuildCraft | 2 +- build.gradle | 26 ++---- common/buildcraft/compat/BCCompat.java | 13 +-- common/buildcraft/compat/BCCompatConfig.java | 56 +++++++++++++ .../module/forge/TilePowerConvertor.java | 6 +- .../compat/module/jei/BCPluginJEI.java | 30 ++++--- .../GuiGhostIngredientHandlerBuildCraft.java | 72 +++++++++++++++++ .../compat/module/rei/BCPluginREI.java | 20 +++-- .../GuiGhostIngredientHandlerBuildCraft.java | 81 +++++++++++++++++++ 9 files changed, 260 insertions(+), 46 deletions(-) create mode 100644 common/buildcraft/compat/BCCompatConfig.java create mode 100644 common/buildcraft/compat/module/jei/gui/GuiGhostIngredientHandlerBuildCraft.java create mode 100644 common/buildcraft/compat/module/rei/gui/GuiGhostIngredientHandlerBuildCraft.java diff --git a/BuildCraft b/BuildCraft index db5ac5e..07d7fcb 160000 --- a/BuildCraft +++ b/BuildCraft @@ -1 +1 @@ -Subproject commit db5ac5eca22b3d86fcae3f150ad405523639d01f +Subproject commit 07d7fcb06fcdc89fcd264752c24e0e27446c3e51 diff --git a/build.gradle b/build.gradle index 7c7dce2..0d67f63 100755 --- a/build.gradle +++ b/build.gradle @@ -93,8 +93,7 @@ minecraft { if (separate) { project.version = config.compat_version } else { -// project.version = config.mod_version; - project.version = config.compat_version + "-" + config.mc_version + "-" + new Date().format("yyyy-MM-dd'T'HH-mm-ssZ") + project.version = config.mod_version; } // def addVersionDetails = !Boolean.getBoolean("release") @@ -257,8 +256,6 @@ repositories { dir 'libs' } -// maven { url = 'https://mvnrepository.com/artifact/net.sf.trove4j/trove4j' } - maven { name 'prog' url 'https://dvs1.progwml6.com/files/maven' @@ -303,7 +300,7 @@ repositories { } } -//// Mixin +// Mixin mixin { add sourceSets.main, "refmap.buildcraft.json" config 'mixins.buildcraft.json' @@ -323,28 +320,28 @@ dependencies { // Examples using mod jars from ./libs + // JEI implementation fg.deobf("mezz.jei:jei-${config.mc_version}-forge:${config.jei_version}") + // REI implementation fg.deobf("me.shedaniel.cloth:cloth-config-forge:${config.cloth_config_version}") implementation fg.deobf("dev.architectury:architectury-forge:${config.architectury_version}") implementation fg.deobf("me.shedaniel:RoughlyEnoughItems-forge:${config.rei_version}") + // Jade implementation fg.deobf("curse.maven:jade-324717:" + config.jade_id) + // CraftTweaker implementation(fg.deobf('com.blamejared.crafttweaker:CraftTweaker-forge-1.20.1:14.0.44')) + // The One Probe implementation fg.deobf("curse.maven:the-one-probe-245211:" + config.top_id) - implementation "net.sf.trove4j:trove4j:3.0.3" - - jarJar(group: 'net.sf.trove4j', name: 'trove4j', version: '[3.0.3,)') { - jarJar.pin(it, '3.0.3') - } - // Testing testImplementation "junit:junit:4.12" testImplementation 'org.hamcrest:hamcrest:2.2' + // Mixin annotationProcessor 'org.spongepowered:mixin:0.8.5:processor' } @@ -522,10 +519,3 @@ tasks.withType(JavaCompile).configureEach { } jar.enabled = true - -// enable Jar-in-Jar -jarJar.enable() - -tasks.named('jarJar') { - // ... -} diff --git a/common/buildcraft/compat/BCCompat.java b/common/buildcraft/compat/BCCompat.java index e3ad066..285b193 100644 --- a/common/buildcraft/compat/BCCompat.java +++ b/common/buildcraft/compat/BCCompat.java @@ -1,13 +1,11 @@ package buildcraft.compat; -import buildcraft.api.BCModules; import buildcraft.api.core.BCLog; import buildcraft.compat.module.crafttweaker.CompatModuleCraftTweaker; import buildcraft.compat.module.ic2.CompatModuleIndustrialCraft2; import buildcraft.compat.module.theoneprobe.CompatModuleTheOneProbe; import buildcraft.core.BCCore; import buildcraft.lib.config.ConfigCategory; -import buildcraft.lib.config.Configuration; import buildcraft.lib.config.EnumRestartRequirement; import buildcraft.lib.registry.RegistryConfig; import buildcraft.lib.registry.TagManager; @@ -54,8 +52,6 @@ public class BCCompat { private static final Map modules = new HashMap<>(); private static final Map> moduleConfigs = new HashMap<>(); - public static Configuration config; - public BCCompat() { instance = this; } @@ -64,7 +60,7 @@ private static void offerAndPreInitModule(CompatModuleBase module) { String cModId = module.compatModId(); if (module.canLoad()) { String _modules = "modules"; - ConfigCategory prop = config + ConfigCategory prop = BCCompatConfig.config .define(_modules, "", EnumRestartRequirement.NONE, @@ -86,10 +82,7 @@ private static void offerAndPreInitModule(CompatModuleBase module) { public static void preInit(FMLConstructModEvent evt) { // Calen RegistryConfig.useOtherModConfigFor(MODID, BCCore.MODID); - - // Start config - BCModules module = BCModules.COMPAT; - config = new Configuration(module); + BCCompatConfig.preInit(); // init BCLog.logger.info(""); @@ -148,6 +141,8 @@ public static void postInit(FMLLoadCompleteEvent evt) { for (CompatModuleBase m : modules.values()) { m.postInit(); } + + BCCompatConfig.saveConfigs(); } private static final TagManager tagManager = new TagManager(); diff --git a/common/buildcraft/compat/BCCompatConfig.java b/common/buildcraft/compat/BCCompatConfig.java new file mode 100644 index 0000000..8ce5d63 --- /dev/null +++ b/common/buildcraft/compat/BCCompatConfig.java @@ -0,0 +1,56 @@ +package buildcraft.compat; + +import buildcraft.api.BCModules; +import buildcraft.lib.config.BCConfig; +import buildcraft.lib.config.ConfigCategory; +import buildcraft.lib.config.Configuration; +import buildcraft.lib.config.EnumRestartRequirement; + +public class BCCompatConfig { + public static Configuration config; + + // Calen: remove the json file + public static boolean coloredPipesVisible; + public static boolean facadesVisible; + private static ConfigCategory propColoredPipesVisible; + private static ConfigCategory propFacadesVisible; + + public static void preInit() { + // Start config + BCModules module = BCModules.COMPAT; + config = new Configuration(module); + createProps(); + reloadConfig(); +// BCCoreConfig.addReloadListener(BCEnergyConfig::reloadConfig); + BCConfig.registerReloadListener(module, BCCompatConfig::reloadConfig); + } + + public static void createProps() { + EnumRestartRequirement world = EnumRestartRequirement.WORLD; + + propColoredPipesVisible = config + .define("client", + "Should all colored pipes be visible in JEI/REI?", + world, + "colored_pipes_visible", false); + + propFacadesVisible = config + .define("client", + "Should all facades be visible in JEI/REI?", + world, + "facades_visible", false); + } + + public static void reloadConfig() { + coloredPipesVisible = propColoredPipesVisible.get(); + facadesVisible = propFacadesVisible.get(); + + saveConfigs(); + } + + public static void saveConfigs() { + if (config.hasChanged()) { + config.save(); + } + } +} diff --git a/common/buildcraft/compat/module/forge/TilePowerConvertor.java b/common/buildcraft/compat/module/forge/TilePowerConvertor.java index 7aeb1e5..8147a0e 100644 --- a/common/buildcraft/compat/module/forge/TilePowerConvertor.java +++ b/common/buildcraft/compat/module/forge/TilePowerConvertor.java @@ -17,7 +17,7 @@ import java.util.Arrays; import java.util.List; -// Calen +// Calen 1.20.1 public class TilePowerConvertor extends TileBC_Neptune implements IEnergyStorage, IMjConnector, IMjReceiver, IMjRedstoneReceiver, IMjReadable, IMjPassiveProvider { public TilePowerConvertor(BlockPos pos, BlockState blockState) { super(BCCompatBlocks.powerConvertorTile.get(), pos, blockState); @@ -247,7 +247,7 @@ public boolean canExtract() { * {@link TilePowerConvertor} and any TileEntity both has {@link ForgeCapabilities#ENERGY} and {@link MjAPI#CAP_CONNECTOR} will be excluded. */ private List> getAllHasCapAround(Capability capability) { - return Arrays.stream(Direction.values()) + return Arrays.stream(Direction.VALUES) .map(d -> new Pair<>(d, this.worldPosition.relative(d))) .filter(p -> this.level.getBlockState(p.getSecond()).getBlock() != BCCompatBlocks.powerConvertor.get()) .map(p -> new Pair<>(p.getFirst(), this.level.getBlockEntity(p.getSecond()))) @@ -267,7 +267,7 @@ private List> getAllHasCapAround(Capability capability } public static int convert_mMJ_2_FE(long mMJ) { - return (int) Math.min(Integer.MAX_VALUE, mMJ / MjAPI.MJ * 16L); + return (int) Math.min(Integer.MAX_VALUE, mMJ * 16L / MjAPI.MJ); } public static long convert_FE_2_mMJ(int fe) { diff --git a/common/buildcraft/compat/module/jei/BCPluginJEI.java b/common/buildcraft/compat/module/jei/BCPluginJEI.java index 74ad674..470e5fb 100644 --- a/common/buildcraft/compat/module/jei/BCPluginJEI.java +++ b/common/buildcraft/compat/module/jei/BCPluginJEI.java @@ -5,10 +5,12 @@ import buildcraft.api.enums.EnumEngineType; import buildcraft.api.fuels.IFuel; import buildcraft.api.recipes.IRefineryRecipeManager; +import buildcraft.compat.BCCompatConfig; import buildcraft.compat.module.jei.energy.combustionengine.CategoryCombustionEngine; 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.gui.GuiGhostIngredientHandlerBuildCraft; import buildcraft.compat.module.jei.gui.GuiHandlerBuildCraft; import buildcraft.compat.module.jei.silicon.CategoryAssemblyTable; import buildcraft.compat.module.jei.transferhandlers.AdvancedCraftingItemsTransferHandler; @@ -69,7 +71,7 @@ public ResourceLocation getPluginUid() { public void registerGuiHandlers(IGuiHandlerRegistration registry) { BCPluginJEI.registryGui = registry; registry.addGenericGuiContainerHandler(GuiBC8.class, new GuiHandlerBuildCraft()); - + registry.addGhostIngredientHandler(GuiBC8.class, new GuiGhostIngredientHandlerBuildCraft()); } // Calen: IRecipeWrapper combined into IRecipeCategory @@ -221,14 +223,22 @@ public void registerItemSubtypes(ISubtypeRegistration registration) { public void onRuntimeAvailable(IJeiRuntime jeiRuntime) { BCPluginJEI.jeiRuntime = jeiRuntime; - // TODO if disable colored pipes - Arrays.stream(DyeColor.values()).forEach( - color -> PipeRegistry.INSTANCE.getAllRegisteredPipes().forEach( - def -> jeiRuntime.getIngredientManager().removeIngredientsAtRuntime( - VanillaTypes.ITEM_STACK, - List.of(new ItemStack((Item) PipeRegistry.INSTANCE.getItemForPipe(def, color))) - ) - ) - ); + if (!BCCompatConfig.coloredPipesVisible) { + Arrays.stream(DyeColor.values()).forEach( + color -> PipeRegistry.INSTANCE.getAllRegisteredPipes().forEach( + def -> jeiRuntime.getIngredientManager().removeIngredientsAtRuntime( + VanillaTypes.ITEM_STACK, + List.of(new ItemStack((Item) PipeRegistry.INSTANCE.getItemForPipe(def, color))) + ) + ) + ); + } + if (!BCCompatConfig.facadesVisible) { + jeiRuntime.getIngredientManager().removeIngredientsAtRuntime( + VanillaTypes.ITEM_STACK, + jeiRuntime.getIngredientManager().getAllIngredients(VanillaTypes.ITEM_STACK).stream() + .filter(stack -> stack.getItem() == BCSiliconItems.plugFacade.get()).toList() + ); + } } } diff --git a/common/buildcraft/compat/module/jei/gui/GuiGhostIngredientHandlerBuildCraft.java b/common/buildcraft/compat/module/jei/gui/GuiGhostIngredientHandlerBuildCraft.java new file mode 100644 index 0000000..425adc6 --- /dev/null +++ b/common/buildcraft/compat/module/jei/gui/GuiGhostIngredientHandlerBuildCraft.java @@ -0,0 +1,72 @@ +package buildcraft.compat.module.jei.gui; + +import buildcraft.core.list.ContainerList; +import buildcraft.core.list.GuiList; +import buildcraft.lib.gui.GuiBC8; +import buildcraft.lib.gui.slot.SlotPhantom; +import com.google.common.collect.Lists; +import mezz.jei.api.gui.handlers.IGhostIngredientHandler; +import mezz.jei.api.ingredients.ITypedIngredient; +import net.minecraft.client.renderer.Rect2i; +import net.minecraft.world.item.ItemStack; + +import java.util.Arrays; +import java.util.List; +import java.util.function.Consumer; + +public class GuiGhostIngredientHandlerBuildCraft implements IGhostIngredientHandler { + @Override + public List> getTargetsTyped(GuiBC8 gui, ITypedIngredient ingredient, boolean doStart) { + if (ingredient.getIngredient() instanceof ItemStack) { + if (gui instanceof GuiList guiList) { + List> ret = Lists.newArrayList(); + for (int lineIndex = 0; lineIndex < guiList.container.lines.length; lineIndex++) { + if (guiList.container.lines[lineIndex].isOneStackMode()) { + ContainerList.WidgetListSlot slot = guiList.container.slots[lineIndex][0]; + ret.add((Target) new SlotPhantomTarget(gui, 8 + 0 * 18, 32 + lineIndex * 34, stack -> guiList.clientSetStackToServer(slot, stack))); + } else { + Arrays.stream(guiList.container.slots[lineIndex]) + .forEach( + slot -> ret.add( + (Target) new SlotPhantomTarget(gui, 8 + slot.slotIndex * 18, 32 + slot.lineIndex * 34, stack -> guiList.clientSetStackToServer(slot, stack)) + ) + ); + } + } + return ret; + } else { + return gui.container.slots.stream() + .filter(s -> s instanceof SlotPhantom) + .map(s -> (SlotPhantom) s) + .map(slot -> (Target) new SlotPhantomTarget(gui, slot.x, slot.y, stack -> gui.container.sendSetPhantomSlot(slot, stack))) + .toList(); + } + } else { + return Lists.newArrayList(); + } + } + + @Override + public void onComplete() { + } + + private static class SlotPhantomTarget implements Target { + private final Rect2i area; + private final Consumer stackConsumer; + + private SlotPhantomTarget(GuiBC8 gui, int slotX, int slotY, Consumer stackConsumer) { + this.area = new Rect2i(gui.getGuiLeft() + slotX, gui.getGuiTop() + slotY, 16, 16); + this.stackConsumer = stackConsumer; + } + + @Override + public Rect2i getArea() { + return area; + } + + @Override + public void accept(ItemStack stack) { + stackConsumer.accept(stack); + } + } +} diff --git a/common/buildcraft/compat/module/rei/BCPluginREI.java b/common/buildcraft/compat/module/rei/BCPluginREI.java index 4b3d308..edf317b 100644 --- a/common/buildcraft/compat/module/rei/BCPluginREI.java +++ b/common/buildcraft/compat/module/rei/BCPluginREI.java @@ -5,9 +5,11 @@ import buildcraft.api.fuels.IFuel; import buildcraft.api.recipes.IAssemblyRecipe; import buildcraft.api.recipes.IRefineryRecipeManager; +import buildcraft.compat.BCCompatConfig; import buildcraft.compat.module.rei.energy.combustionengine.CategoryCombustionEngine; import buildcraft.compat.module.rei.energy.combustionengine.DisplayCombustionEngine; import buildcraft.compat.module.rei.factory.*; +import buildcraft.compat.module.rei.gui.GuiGhostIngredientHandlerBuildCraft; import buildcraft.compat.module.rei.gui.GuiHandlerBuildCraft; import buildcraft.compat.module.rei.silicon.CategoryAssemblyTable; import buildcraft.compat.module.rei.silicon.DisplayAssembly; @@ -23,6 +25,7 @@ import me.shedaniel.rei.api.client.registry.display.DisplayRegistry; import me.shedaniel.rei.api.client.registry.entry.EntryRegistry; import me.shedaniel.rei.api.client.registry.screen.ExclusionZones; +import me.shedaniel.rei.api.client.registry.screen.ScreenRegistry; import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes; import me.shedaniel.rei.api.common.util.EntryStacks; import me.shedaniel.rei.forge.REIPluginClient; @@ -95,16 +98,23 @@ public void registerEntries(EntryRegistry registry) { if (item == BCCoreItems.fragileFluidShard.get()) { return true; } else if (item instanceof ItemPipeHolder pipe) { - // TODO if disable colored piped - if (pipe.getColour() != DyeColor.WHITE) { - return true; + if (!BCCompatConfig.coloredPipesVisible) { + if (pipe.getColour() != DyeColor.WHITE) { + return true; + } } } else if (item == BCSiliconItems.plugFacade.get()) { - // TODO if disable rei facades - return true; + if (!BCCompatConfig.facadesVisible) { + return true; + } } } return false; }); } + + @Override + public void registerScreens(ScreenRegistry registry) { + registry.registerDraggableStackVisitor(new GuiGhostIngredientHandlerBuildCraft()); + } } diff --git a/common/buildcraft/compat/module/rei/gui/GuiGhostIngredientHandlerBuildCraft.java b/common/buildcraft/compat/module/rei/gui/GuiGhostIngredientHandlerBuildCraft.java new file mode 100644 index 0000000..b8bba40 --- /dev/null +++ b/common/buildcraft/compat/module/rei/gui/GuiGhostIngredientHandlerBuildCraft.java @@ -0,0 +1,81 @@ +package buildcraft.compat.module.rei.gui; + +import buildcraft.core.list.GuiList; +import buildcraft.lib.gui.GuiBC8; +import buildcraft.lib.gui.slot.SlotPhantom; +import com.google.common.collect.Lists; +import me.shedaniel.math.Point; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.gui.drag.DraggableStack; +import me.shedaniel.rei.api.client.gui.drag.DraggableStackVisitor; +import me.shedaniel.rei.api.client.gui.drag.DraggedAcceptorResult; +import me.shedaniel.rei.api.client.gui.drag.DraggingContext; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes; +import net.minecraft.client.gui.screens.Screen; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Stream; + +public class GuiGhostIngredientHandlerBuildCraft implements DraggableStackVisitor> { + @Override + public boolean isHandingScreen(R screen) { + return screen instanceof GuiBC8; + } + + @Override + public Stream getDraggableAcceptingBounds(DraggingContext> context, DraggableStack stack) { + EntryStack entryStack = stack.getStack(); + if (entryStack.getType() == VanillaEntryTypes.ITEM) { + GuiBC8 gui = context.getScreen(); + if (gui instanceof GuiList guiList) { + List retList = Lists.newArrayList(); + for (int lineIndex = 0; lineIndex < guiList.container.lines.length; lineIndex++) { + if (guiList.container.lines[lineIndex].isOneStackMode()) { + retList.add(BoundsProvider.ofRectangle(new Rectangle(gui.getGuiLeft() + 8 + 0 * 18, gui.getGuiTop() + 32 + lineIndex * 34, 16, 16))); + } else { + Arrays.stream(guiList.container.slots[lineIndex]) + .forEach( + slot -> retList.add( + BoundsProvider.ofRectangle(new Rectangle(gui.getGuiLeft() + 8 + slot.slotIndex * 18, gui.getGuiTop() + 32 + slot.lineIndex * 34)) + ) + ); + } + } + return retList.stream(); + } else { + return gui.container.slots.stream() + .filter(slot -> slot instanceof SlotPhantom) + .map(slot -> BoundsProvider.ofRectangle(new Rectangle(gui.getGuiLeft() + slot.x, gui.getGuiTop() + slot.y, 16, 16))); + } + } else { + return Stream.builder().build(); + } + } + + @Override + public DraggedAcceptorResult acceptDraggedStack(DraggingContext> context, DraggableStack stack) { + Point position = context.getCurrentPosition(); + GuiBC8 gui = context.getScreen(); + EntryStack entryStack = stack.getStack(); + if (entryStack.getType() == VanillaEntryTypes.ITEM) { + if (gui instanceof GuiList guiList) { + Arrays.stream(guiList.container.slots) + .flatMap(Arrays::stream) + .filter(slot -> slot.slotIndex == 0 || !guiList.container.lines[slot.lineIndex].isOneStackMode()) + .filter(slot -> new Rectangle(gui.getGuiLeft() + 8 + slot.slotIndex * 18, gui.getGuiTop() + 32 + slot.lineIndex * 34, 16, 16).contains(position)) + .forEach(slot -> guiList.clientSetStackToServer(slot, entryStack.castValue())); + } else { + gui.container.slots.stream() + .filter(slot -> slot instanceof SlotPhantom) + .filter(slot -> new Rectangle(gui.getGuiLeft() + slot.x, gui.getGuiTop() + slot.y, 16, 16).contains(position)) + .map(slot -> (SlotPhantom) slot) + .forEach(slotPhantom -> gui.container.sendSetPhantomSlot(slotPhantom, entryStack.castValue())); + } + return DraggedAcceptorResult.ACCEPTED; + } else { + return DraggedAcceptorResult.PASS; + } + } +} From 0d121ab665f914cb4e4c32fe8e9884f89257b209 Mon Sep 17 00:00:00 2001 From: CalenXwX Date: Sat, 25 Jan 2025 12:04:07 +0800 Subject: [PATCH 5/9] Replaced power convertor with FE engine --- common/buildcraft/compat/BCCompat.java | 9 +- common/buildcraft/compat/BCCompatBlocks.java | 20 +- common/buildcraft/compat/BCCompatModels.java | 121 ++++++++ common/buildcraft/compat/BCCompatProxy.java | 42 +++ .../datagen/CompatBlockStateGenerator.java | 11 +- .../datagen/CompatItemModelGenerator.java | 5 +- .../forge/BlockEnergyCompatEngine_BC8.java | 15 + .../module/forge/BlockPowerConvertor.java | 17 -- .../forge/EnumEnergyCompatEngineTypes.java | 21 ++ .../compat/module/forge/RenderEngineFe.java | 20 ++ .../compat/module/forge/TileEngineFe.java | 113 +++++++ .../module/forge/TilePowerConvertor.java | 276 ------------------ 12 files changed, 356 insertions(+), 314 deletions(-) create mode 100644 common/buildcraft/compat/BCCompatModels.java create mode 100644 common/buildcraft/compat/BCCompatProxy.java create mode 100644 common/buildcraft/compat/module/forge/BlockEnergyCompatEngine_BC8.java delete mode 100644 common/buildcraft/compat/module/forge/BlockPowerConvertor.java create mode 100644 common/buildcraft/compat/module/forge/EnumEnergyCompatEngineTypes.java create mode 100644 common/buildcraft/compat/module/forge/RenderEngineFe.java create mode 100644 common/buildcraft/compat/module/forge/TileEngineFe.java delete mode 100644 common/buildcraft/compat/module/forge/TilePowerConvertor.java diff --git a/common/buildcraft/compat/BCCompat.java b/common/buildcraft/compat/BCCompat.java index 285b193..35f3605 100644 --- a/common/buildcraft/compat/BCCompat.java +++ b/common/buildcraft/compat/BCCompat.java @@ -109,6 +109,9 @@ public static void preInit(FMLConstructModEvent evt) { // Calen BCCompatBlocks.fmlPreInit(); + + // Calen 1.20.1 + BCCompatProxy.getProxy().fmlPreInit(); } /** This is called after config loaded. */ @@ -150,9 +153,9 @@ public static void postInit(FMLLoadCompleteEvent evt) { static { startBatch(); - registerTag("item.block.power_convertor").reg("power_convertor").locale("power_convertor"); - registerTag("block.power_convertor").reg("power_convertor").locale("power_convertor"); - registerTag("tile.power_convertor").reg("power_convertor"); + registerTag("item.block.engine.bc.fe").reg("engine_fe").locale("engineFe"); + registerTag("block.engine.bc.fe").reg("engine_fe").locale("engineFe"); + registerTag("tile.engine.fe").reg("engine_fe"); endBatch(TagManager.prependTags("buildcraftcompat:", TagManager.EnumTagType.REGISTRY_NAME) .andThen(TagManager.setTab("buildcraft.main")) diff --git a/common/buildcraft/compat/BCCompatBlocks.java b/common/buildcraft/compat/BCCompatBlocks.java index 1036710..ed42cad 100644 --- a/common/buildcraft/compat/BCCompatBlocks.java +++ b/common/buildcraft/compat/BCCompatBlocks.java @@ -1,20 +1,28 @@ package buildcraft.compat; -import buildcraft.compat.module.forge.BlockPowerConvertor; -import buildcraft.compat.module.forge.TilePowerConvertor; +import buildcraft.compat.module.forge.BlockEnergyCompatEngine_BC8; +import buildcraft.compat.module.forge.EnumEnergyCompatEngineTypes; +import buildcraft.compat.module.forge.TileEngineFe; +import buildcraft.core.item.ItemEngine_BC8; import buildcraft.lib.block.BlockPropertiesCreator; import buildcraft.lib.registry.RegistrationHelper; +import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraftforge.registries.RegistryObject; public class BCCompatBlocks { public static final RegistrationHelper HELPER = new RegistrationHelper(BCCompat.MODID); - public static final RegistryObject powerConvertor; - public static final RegistryObject> powerConvertorTile; + public static final RegistryObject engineFe; + public static final RegistryObject> engineFeTile; static { - powerConvertor = HELPER.addBlockAndItem("block.power_convertor", BlockPropertiesCreator.metal(), BlockPowerConvertor::new); - powerConvertorTile = HELPER.registerTile("tile.power_convertor", TilePowerConvertor::new, powerConvertor); + engineFe = HELPER.addBlockAndItem("block.engine.bc." + EnumEnergyCompatEngineTypes.FE.getSerializedName(), + BlockPropertiesCreator.metal() + .strength(5.0F, 10.0F) + .sound(SoundType.METAL) + .noOcclusion() + , (idBC, properties) -> new BlockEnergyCompatEngine_BC8(idBC, properties, EnumEnergyCompatEngineTypes.FE, TileEngineFe::new), ItemEngine_BC8::new); + engineFeTile = HELPER.registerTile("tile.engine.fe", TileEngineFe::new, engineFe); } public static void fmlPreInit() { diff --git a/common/buildcraft/compat/BCCompatModels.java b/common/buildcraft/compat/BCCompatModels.java new file mode 100644 index 0000000..c12cc4d --- /dev/null +++ b/common/buildcraft/compat/BCCompatModels.java @@ -0,0 +1,121 @@ +package buildcraft.compat; + +import buildcraft.api.enums.EnumPowerStage; +import buildcraft.compat.module.forge.EnumEnergyCompatEngineTypes; +import buildcraft.compat.module.forge.RenderEngineFe; +import buildcraft.compat.module.forge.TileEngineFe; +import buildcraft.core.block.BlockEngine_BC8; +import buildcraft.lib.client.model.ModelHolderVariable; +import buildcraft.lib.client.model.ModelItemSimple; +import buildcraft.lib.client.model.MutableQuad; +import buildcraft.lib.engine.TileEngineBase_BC8; +import buildcraft.lib.expression.DefaultContexts; +import buildcraft.lib.expression.FunctionContext; +import buildcraft.lib.expression.node.value.NodeVariableDouble; +import buildcraft.lib.expression.node.value.NodeVariableObject; +import buildcraft.lib.misc.ExpressionCompat; +import buildcraft.lib.misc.data.ModelVariableData; +import com.google.common.collect.Lists; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderers; +import net.minecraft.client.renderer.texture.TextureAtlas; +import net.minecraft.client.resources.model.ModelResourceLocation; +import net.minecraft.core.Direction; +import net.minecraft.util.LazyLoadedValue; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.event.EntityRenderersEvent; +import net.minecraftforge.client.event.ModelEvent; +import net.minecraftforge.client.event.TextureStitchEvent; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.ModList; +import net.minecraftforge.fml.javafmlmod.FMLModContainer; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +@OnlyIn(Dist.CLIENT) +public class BCCompatModels { + private static final NodeVariableDouble ENGINE_PROGRESS; + private static final NodeVariableObject ENGINE_STAGE; + private static final NodeVariableObject ENGINE_FACING; + + private static final ModelHolderVariable ENGINE_FE; + + static { + FunctionContext fnCtx = new FunctionContext(ExpressionCompat.ENUM_POWER_STAGE, DefaultContexts.createWithAll()); + ENGINE_PROGRESS = fnCtx.putVariableDouble("progress"); + ENGINE_STAGE = fnCtx.putVariableObject("stage", EnumPowerStage.class); + ENGINE_FACING = fnCtx.putVariableObject("direction", Direction.class); + // TODO: Item models from "item/engine_stone.json" + ENGINE_FE = new ModelHolderVariable( + "buildcraftcompat:models/tile/engine_fe.jsonbc", + fnCtx + ); + BlockEngine_BC8.setModel(EnumEnergyCompatEngineTypes.FE, ENGINE_FE); + } + + public static void fmlPreInit() { + // 1.18.2: following events are IModBusEvent + IEventBus modEventBus = ((FMLModContainer) ModList.get().getModContainerById(BCCompat.MODID).get()).getEventBus(); + modEventBus.register(BCCompatModels.class); + } + + @SubscribeEvent + public static void onTesrReg(EntityRenderersEvent.RegisterRenderers event) { + BlockEntityRenderers.register(BCCompatBlocks.engineFeTile.get(), RenderEngineFe::new); + } + + // Calen 1.20.1 + private static final List spriteTasks = Lists.newLinkedList(); + + // Calen 1.20.1 + @SubscribeEvent + public static void onTextureStitchEvent$Post(TextureStitchEvent.Post event) { + if (event.getAtlas().location().equals(TextureAtlas.LOCATION_BLOCKS)) { + spriteTasks.forEach(Runnable::run); + } + } + + @SubscribeEvent + public static void onModelBake(ModelEvent.ModifyBakingResult event) { + ENGINE_PROGRESS.value = 0.2; + ENGINE_STAGE.value = EnumPowerStage.BLUE; + ENGINE_FACING.value = Direction.UP; + ModelVariableData varData = new ModelVariableData(); + varData.setNodes(ENGINE_FE.createTickableNodes()); + varData.tick(); + varData.refresh(); + event.getModels().put( + new ModelResourceLocation(BCCompatBlocks.engineFe.getId(), "inventory"), + new ModelItemSimple( + new LazyLoadedValue<>( + () -> Arrays.stream(ENGINE_FE.getCutoutQuads()) + .map(MutableQuad::toBakedItem) + .collect(Collectors.toList()) + ), + ModelItemSimple.TRANSFORM_BLOCK, + true, + spriteTasks::add + ) + ); + } + + private static MutableQuad[] getEngineQuads(ModelHolderVariable model, + TileEngineBase_BC8 tile, + float partialTicks) { + ENGINE_PROGRESS.value = tile.getProgressClient(partialTicks); + ENGINE_STAGE.value = tile.getPowerStage(); + ENGINE_FACING.value = tile.getCurrentFacing(); + if (tile.clientModelData.hasNoNodes()) { + tile.clientModelData.setNodes(model.createTickableNodes()); + } + tile.clientModelData.refresh(); + return model.getCutoutQuads(); + } + + public static MutableQuad[] getFeEngineQuads(TileEngineFe tile, float partialTicks) { + return getEngineQuads(ENGINE_FE, tile, partialTicks); + } +} diff --git a/common/buildcraft/compat/BCCompatProxy.java b/common/buildcraft/compat/BCCompatProxy.java new file mode 100644 index 0000000..53d6419 --- /dev/null +++ b/common/buildcraft/compat/BCCompatProxy.java @@ -0,0 +1,42 @@ +package buildcraft.compat; + +import net.minecraftforge.fml.loading.FMLLoader; + +public abstract class BCCompatProxy { + private static BCCompatProxy proxy = null; + + public static BCCompatProxy getProxy() { + if (proxy == null) { + switch (FMLLoader.getDist()) { + case CLIENT: + proxy = new BCCompatProxy.ClientProxy(); + break; + case DEDICATED_SERVER: + proxy = new BCCompatProxy.ServerProxy(); + break; + } + } + return proxy; + } + + public void fmlPreInit() { + } + + public void fmlInit() { + } + + public void fmlPostInit() { + } + + public static class ServerProxy extends BCCompatProxy { + + } + + public static class ClientProxy extends BCCompatProxy { + @Override + public void fmlPreInit() { + super.fmlPreInit(); + BCCompatModels.fmlPreInit(); + } + } +} diff --git a/common/buildcraft/compat/datagen/CompatBlockStateGenerator.java b/common/buildcraft/compat/datagen/CompatBlockStateGenerator.java index 07b01c4..7c6374b 100644 --- a/common/buildcraft/compat/datagen/CompatBlockStateGenerator.java +++ b/common/buildcraft/compat/datagen/CompatBlockStateGenerator.java @@ -4,7 +4,6 @@ import buildcraft.compat.BCCompatBlocks; import buildcraft.datagen.base.BCBaseBlockStateGenerator; import net.minecraft.data.PackOutput; -import net.minecraftforge.client.model.generators.ConfiguredModel; import net.minecraftforge.common.data.ExistingFileHelper; public class CompatBlockStateGenerator extends BCBaseBlockStateGenerator { @@ -14,13 +13,7 @@ public CompatBlockStateGenerator(PackOutput output, ExistingFileHelper exFileHel @Override protected void registerStatesAndModels() { - // power_convertor - getVariantBuilder(BCCompatBlocks.powerConvertor.get()).forAllStates(s -> - ConfiguredModel.builder().modelFile( - models().withExistingParent("buildcraftcompat:block/power_convertor", CUBE_ALL) - .texture("all", "buildcraftcompat:block/power_convertor") - ) - .build() - ); + // fe engine + builtinEntity(BCCompatBlocks.engineFe.get(), "buildcraftcompat:block/engine/fe/back"); } } diff --git a/common/buildcraft/compat/datagen/CompatItemModelGenerator.java b/common/buildcraft/compat/datagen/CompatItemModelGenerator.java index 3f43044..cba884b 100644 --- a/common/buildcraft/compat/datagen/CompatItemModelGenerator.java +++ b/common/buildcraft/compat/datagen/CompatItemModelGenerator.java @@ -4,7 +4,6 @@ import buildcraft.compat.BCCompatBlocks; import buildcraft.datagen.base.BCBaseItemModelGenerator; import net.minecraft.data.PackOutput; -import net.minecraft.resources.ResourceLocation; import net.minecraftforge.common.data.ExistingFileHelper; public class CompatItemModelGenerator extends BCBaseItemModelGenerator { @@ -14,7 +13,7 @@ public CompatItemModelGenerator(PackOutput output, ExistingFileHelper existingFi @Override protected void registerModels() { - // power_convertor - withExistingParent(BCCompatBlocks.powerConvertor.get().getRegistryName().toString(), new ResourceLocation("buildcraftcompat:block/power_convertor")); + // fe engine + getBuilder(BCCompatBlocks.engineFe.get().getRegistryName().toString()).parent(BUILTIN_ENTITY); } } diff --git a/common/buildcraft/compat/module/forge/BlockEnergyCompatEngine_BC8.java b/common/buildcraft/compat/module/forge/BlockEnergyCompatEngine_BC8.java new file mode 100644 index 0000000..8197654 --- /dev/null +++ b/common/buildcraft/compat/module/forge/BlockEnergyCompatEngine_BC8.java @@ -0,0 +1,15 @@ +package buildcraft.compat.module.forge; + +import buildcraft.lib.engine.BlockEngineBase_BC8; +import buildcraft.lib.engine.TileEngineBase_BC8; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; + +import java.util.function.BiFunction; + +public class BlockEnergyCompatEngine_BC8 extends BlockEngineBase_BC8 { + public BlockEnergyCompatEngine_BC8(String idBC, BlockBehaviour.Properties properties, EnumEnergyCompatEngineTypes type, BiFunction engineTileConstructor) { + super(idBC, properties, type, engineTileConstructor); + } +} diff --git a/common/buildcraft/compat/module/forge/BlockPowerConvertor.java b/common/buildcraft/compat/module/forge/BlockPowerConvertor.java deleted file mode 100644 index 8e8c32c..0000000 --- a/common/buildcraft/compat/module/forge/BlockPowerConvertor.java +++ /dev/null @@ -1,17 +0,0 @@ -package buildcraft.compat.module.forge; - -import buildcraft.lib.block.BlockBCTile_Neptune; -import buildcraft.lib.tile.TileBC_Neptune; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.block.state.BlockState; - -public class BlockPowerConvertor extends BlockBCTile_Neptune { - public BlockPowerConvertor(String idBC, Properties props) { - super(idBC, props); - } - - @Override - public TileBC_Neptune newBlockEntity(BlockPos pos, BlockState state) { - return new TilePowerConvertor(pos, state); - } -} diff --git a/common/buildcraft/compat/module/forge/EnumEnergyCompatEngineTypes.java b/common/buildcraft/compat/module/forge/EnumEnergyCompatEngineTypes.java new file mode 100644 index 0000000..a1053b2 --- /dev/null +++ b/common/buildcraft/compat/module/forge/EnumEnergyCompatEngineTypes.java @@ -0,0 +1,21 @@ +package buildcraft.compat.module.forge; + +import buildcraft.api.core.IEngineType; +import net.minecraft.util.StringRepresentable; + +public enum EnumEnergyCompatEngineTypes implements StringRepresentable, IEngineType { + FE("compat", "fe"); + + public static final EnumEnergyCompatEngineTypes[] VALUES = values(); + + public final String unlocalizedTag; + + EnumEnergyCompatEngineTypes(String mod, String loc) { + unlocalizedTag = loc; + } + + @Override + public String getSerializedName() { + return unlocalizedTag; + } +} diff --git a/common/buildcraft/compat/module/forge/RenderEngineFe.java b/common/buildcraft/compat/module/forge/RenderEngineFe.java new file mode 100644 index 0000000..8bef1b2 --- /dev/null +++ b/common/buildcraft/compat/module/forge/RenderEngineFe.java @@ -0,0 +1,20 @@ +package buildcraft.compat.module.forge; + +import buildcraft.compat.BCCompatModels; +import buildcraft.lib.client.model.MutableQuad; +import buildcraft.lib.client.render.tile.RenderEngine_BC8; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +@OnlyIn(Dist.CLIENT) +public class RenderEngineFe extends RenderEngine_BC8 { + public RenderEngineFe(BlockEntityRendererProvider.Context context) { + super(context); + } + + @Override + protected MutableQuad[] getEngineModel(TileEngineFe engine, float partialTicks) { + return BCCompatModels.getFeEngineQuads(engine, partialTicks); + } +} diff --git a/common/buildcraft/compat/module/forge/TileEngineFe.java b/common/buildcraft/compat/module/forge/TileEngineFe.java new file mode 100644 index 0000000..bfb0c90 --- /dev/null +++ b/common/buildcraft/compat/module/forge/TileEngineFe.java @@ -0,0 +1,113 @@ +package buildcraft.compat.module.forge; + +import buildcraft.api.core.EnumPipePart; +import buildcraft.api.enums.EnumPowerStage; +import buildcraft.api.mj.IMjConnector; +import buildcraft.api.mj.MjAPI; +import buildcraft.compat.BCCompatBlocks; +import buildcraft.lib.engine.EngineConnector; +import buildcraft.lib.engine.TileEngineBase_BC8; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.capabilities.ForgeCapabilities; +import net.minecraftforge.energy.IEnergyStorage; +import org.jetbrains.annotations.NotNull; + +public class TileEngineFe extends TileEngineBase_BC8 { + private static final int MJ_CAP = 10_000; + private static final int FE_CAP = convert_mMJ_2_FE(MJ_CAP * MjAPI.MJ); + + private final IEnergyStorage feStorage = new IEnergyStorage() { + @Override + public int receiveEnergy(int maxReceive, boolean simulate) { + int received_FE = Math.min(convert_mMJ_2_FE(TileEngineFe.this.getMaxPower() - TileEngineFe.this.getEnergyStored()), maxReceive); + if (!simulate) { + addPower(convert_FE_2_mMJ(received_FE)); + } + return received_FE; + } + + @Override + public int extractEnergy(int maxExtract, boolean simulate) { + return 0; + } + + @Override + public int getEnergyStored() { + return convert_mMJ_2_FE(TileEngineFe.this.getEnergyStored()); + } + + @Override + public int getMaxEnergyStored() { + return FE_CAP; + } + + @Override + public boolean canExtract() { + return false; + } + + @Override + public boolean canReceive() { + return true; + } + }; + + public TileEngineFe(BlockPos pos, BlockState blockState) { + super(BCCompatBlocks.engineFeTile.get(), pos, blockState); + caps.addCapabilityInstance(ForgeCapabilities.ENERGY, this.feStorage, EnumPipePart.VALUES); + } + + @NotNull + @Override + protected IMjConnector createConnector() { + return new EngineConnector(false); + } + + @Override + public boolean isBurning() { + return isRedstonePowered; + } + + @Override + public long getMaxPower() { + return MJ_CAP * MjAPI.MJ; + } + + @Override + public long maxPowerReceived() { + return 2_000 * MjAPI.MJ; + } + + @Override + public long maxPowerExtracted() { + return 1_000 * MjAPI.MJ; + } + + @Override + public float explosionRange() { + return 0; + } + + @Override + public long getCurrentOutput() { + return 256 * MjAPI.MJ; + } + + @Override + protected EnumPowerStage computePowerStage() { + return EnumPowerStage.RED; + } + + @Override + protected void burn() { + } + + public static int convert_mMJ_2_FE(long mMJ) { + return (int) Math.min(Integer.MAX_VALUE, mMJ * 16L / MjAPI.MJ); + } + + public static long convert_FE_2_mMJ(int fe) { + return fe * MjAPI.MJ / 16L; + } +} diff --git a/common/buildcraft/compat/module/forge/TilePowerConvertor.java b/common/buildcraft/compat/module/forge/TilePowerConvertor.java deleted file mode 100644 index 8147a0e..0000000 --- a/common/buildcraft/compat/module/forge/TilePowerConvertor.java +++ /dev/null @@ -1,276 +0,0 @@ -package buildcraft.compat.module.forge; - -import buildcraft.api.core.EnumPipePart; -import buildcraft.api.mj.*; -import buildcraft.compat.BCCompatBlocks; -import buildcraft.lib.tile.TileBC_Neptune; -import com.mojang.datafixers.util.Pair; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.capabilities.ForgeCapabilities; -import net.minecraftforge.energy.IEnergyStorage; - -import javax.annotation.Nonnull; -import java.util.Arrays; -import java.util.List; - -// Calen 1.20.1 -public class TilePowerConvertor extends TileBC_Neptune implements IEnergyStorage, IMjConnector, IMjReceiver, IMjRedstoneReceiver, IMjReadable, IMjPassiveProvider { - public TilePowerConvertor(BlockPos pos, BlockState blockState) { - super(BCCompatBlocks.powerConvertorTile.get(), pos, blockState); - caps.addCapabilityInstance(ForgeCapabilities.ENERGY, this, EnumPipePart.VALUES); - caps.addCapabilityInstance(MjAPI.CAP_CONNECTOR, this, EnumPipePart.VALUES); - caps.addCapabilityInstance(MjAPI.CAP_REDSTONE_RECEIVER, this, EnumPipePart.VALUES); - caps.addCapabilityInstance(MjAPI.CAP_READABLE, this, EnumPipePart.VALUES); - caps.addCapabilityInstance(MjAPI.CAP_RECEIVER, this, EnumPipePart.VALUES); - caps.addCapabilityInstance(MjAPI.CAP_PASSIVE_PROVIDER, this, EnumPipePart.VALUES); - } - - // IMjConnector - @Override - public boolean canConnect(@Nonnull IMjConnector other) { - return true; - } - - // IMjPassiveProvider - @Override - public long extractPower(long min, long max, final boolean simulate) { - int min_FE = convert_mMJ_2_FE(min); - int max_FE = convert_mMJ_2_FE(max); - List> toQuery = getAllHasCapAround(ForgeCapabilities.ENERGY); - // try getting power from each IEnergyStorage in toQuery - List>> queried = toQuery.stream().map(p -> { - IEnergyStorage energyStorage = p.getSecond(); - int extractedFE = energyStorage.extractEnergy(max_FE, true); - return new Pair<>(p.getFirst(), new Pair<>(p.getSecond(), extractedFE)); - }) - .filter(p -> p.getSecond().getSecond() > 0) - .toList(); - // get max power can get - int neighbourTotalCanProvide_FE = 0; - for (Pair> p : queried) { - neighbourTotalCanProvide_FE += p.getSecond().getSecond(); - } - if (neighbourTotalCanProvide_FE < min_FE) { - // if cannot support [min], fail - return 0; - } else { - // if can support [min] - final int final_neighbourTotalCanProvide_FE = neighbourTotalCanProvide_FE; - // if can provide more than [max], each provides weighted average value - if (neighbourTotalCanProvide_FE > max_FE) { - queried = queried.stream() - .map(p -> new Pair<>(p.getFirst(), new Pair<>(p.getSecond().getFirst(), p.getSecond().getSecond() * max_FE / final_neighbourTotalCanProvide_FE))) - .toList(); - } - // extract! - int trueExtracted_FE = 0; - for (Pair> p : queried) { - trueExtracted_FE += p.getSecond().getFirst().extractEnergy(p.getSecond().getSecond(), simulate); - } - return convert_FE_2_mMJ(trueExtracted_FE); - } - } - - // IMjReadable - @Override - public long getStored() { - List> toQuery = getAllHasCapAround(ForgeCapabilities.ENERGY); - int stored_FE = 0; - for (Pair p : toQuery) { - stored_FE += p.getSecond().getEnergyStored(); - } - return convert_FE_2_mMJ(stored_FE); - } - - // IMjReadable - @Override - public long getCapacity() { - List> toQuery = getAllHasCapAround(ForgeCapabilities.ENERGY); - int stored_FE = 0; - for (Pair p : toQuery) { - stored_FE += p.getSecond().getMaxEnergyStored(); - } - return convert_FE_2_mMJ(stored_FE); - } - - // IMjReceiver - @Override - public long getPowerRequested() { - List> toQuery = getAllHasCapAround(ForgeCapabilities.ENERGY); - int stored_FE = 0; - for (Pair p : toQuery) { - IEnergyStorage capFE = p.getSecond(); - stored_FE += capFE.canReceive() ? Math.max(capFE.receiveEnergy(Integer.MAX_VALUE, true), 0) : 0; - } - return convert_FE_2_mMJ(stored_FE); - } - - // IMjReceiver - @Override - public long receivePower(long max_mMJ, boolean simulate) { - int max_FE = convert_mMJ_2_FE(max_mMJ); - List> toQuery = getAllHasCapAround(ForgeCapabilities.ENERGY); - // try getting power from each IEnergyStorage in toQuery - List>> queried = toQuery.stream().map(p -> { - IEnergyStorage energyStorage = p.getSecond(); - int receivedFE = energyStorage.receiveEnergy(max_FE, true); - return new Pair<>(p.getFirst(), new Pair<>(p.getSecond(), receivedFE)); - }) - .filter(p -> p.getSecond().getSecond() > 0) - .toList(); - // get max power can receive - int neighbourTotalCanReceive_FE = 0; - for (Pair> p : queried) { - neighbourTotalCanReceive_FE += p.getSecond().getSecond(); - } - // if can provide more than [max], each provides weighted average value - final int final_neighbourTotalCanReceive_FE = neighbourTotalCanReceive_FE; - if (neighbourTotalCanReceive_FE > max_FE) { - queried = queried.stream() - .map(p -> new Pair<>(p.getFirst(), new Pair<>(p.getSecond().getFirst(), p.getSecond().getSecond() * max_FE / final_neighbourTotalCanReceive_FE))) - .toList(); - } - // receive! - int trueReceived_FE = 0; - for (Pair> p : queried) { - trueReceived_FE += p.getSecond().getFirst().receiveEnergy(p.getSecond().getSecond(), simulate); - } - int trueExcess_FE = max_FE - trueReceived_FE; - return convert_FE_2_mMJ(trueExcess_FE); - } - - // IEnergyStorage - // IMjReceiver - @Override - public boolean canReceive() { - return true; - } - - // IEnergyStorage - @Override - public int receiveEnergy(int max_FE, boolean simulate) { - long max_mMJ = convert_FE_2_mMJ(max_FE); - List> toQuery = getAllHasCapAround(MjAPI.CAP_RECEIVER); - // try getting power from each IMjReceiver in toQuery - List>> queried = toQuery.stream().map(p -> { - IMjReceiver mjReceiver = p.getSecond(); - long excess_FE = mjReceiver.receivePower(max_mMJ, true); - long received_FE = max_mMJ - excess_FE; - return new Pair<>(p.getFirst(), new Pair<>(p.getSecond(), received_FE)); - }) - .filter(p -> p.getSecond().getSecond() > 0) - .toList(); - // get max power can receive - long neighbourTotalCanReceive_FE = 0; - for (Pair> p : queried) { - neighbourTotalCanReceive_FE += p.getSecond().getSecond(); - } - // if can provide more than [max], each provides weighted average value - final long final_neighbourTotalCanReceive_FE = neighbourTotalCanReceive_FE; - if (neighbourTotalCanReceive_FE > max_mMJ) { - queried = queried.stream() - .map(p -> new Pair<>(p.getFirst(), new Pair<>(p.getSecond().getFirst(), p.getSecond().getSecond() * max_mMJ / final_neighbourTotalCanReceive_FE))) - .toList(); - } - // receive! - long trueExcess_FE = 0; - for (Pair> p : queried) { - trueExcess_FE += p.getSecond().getFirst().receivePower(p.getSecond().getSecond(), simulate); - } - long trueReceived_FE = max_FE - trueExcess_FE; - return convert_mMJ_2_FE(trueReceived_FE); - } - - @Override - public int extractEnergy(int max_FE, boolean simulate) { - long max_mMJ = convert_FE_2_mMJ(max_FE); - List> toQuery = getAllHasCapAround(MjAPI.CAP_PASSIVE_PROVIDER); - // try getting power from each IEnergyStorage in toQuery - List>> queried = toQuery.stream().map(p -> { - IMjPassiveProvider energyStorage = p.getSecond(); - long extractedFE = energyStorage.extractPower(0, max_mMJ, true); - return new Pair<>(p.getFirst(), new Pair<>(p.getSecond(), extractedFE)); - }) - .filter(p -> p.getSecond().getSecond() > 0) - .toList(); - // get max power can get - long neighbourTotalCanProvide_mMJ = 0; - for (Pair> p : queried) { - neighbourTotalCanProvide_mMJ += p.getSecond().getSecond(); - } - // if can provide more than [max], each provides weighted average value - final long final_neighbourTotalCanProvide_FE = neighbourTotalCanProvide_mMJ; - if (neighbourTotalCanProvide_mMJ > max_mMJ) { - queried = queried.stream() - .map(p -> new Pair<>(p.getFirst(), new Pair<>(p.getSecond().getFirst(), p.getSecond().getSecond() * max_mMJ / final_neighbourTotalCanProvide_FE))) - .toList(); - } - // extract! - long trueExtracted_mMJ = 0; - for (Pair> p : queried) { - trueExtracted_mMJ += p.getSecond().getFirst().extractPower(0, p.getSecond().getSecond(), simulate); - } - return convert_mMJ_2_FE(trueExtracted_mMJ); - } - - @Override - public int getEnergyStored() { - List> toQuery = getAllHasCapAround(MjAPI.CAP_READABLE); - long neighbourTotalEnergyStored_mMJ = 0; - for (Pair p : toQuery) { - neighbourTotalEnergyStored_mMJ += p.getSecond().getStored(); - } - return convert_mMJ_2_FE(neighbourTotalEnergyStored_mMJ); - } - - @Override - public int getMaxEnergyStored() { - List> toQuery = getAllHasCapAround(MjAPI.CAP_READABLE); - long neighbourTotalMaxEnergyStored_mMJ = 0; - for (Pair p : toQuery) { - neighbourTotalMaxEnergyStored_mMJ += p.getSecond().getCapacity(); - } - return convert_mMJ_2_FE(neighbourTotalMaxEnergyStored_mMJ); - } - - @Override - public boolean canExtract() { - return true; - } - - /** - * To get all capability instances of capability provider TileEntities all around this. - * {@link TilePowerConvertor} and any TileEntity both has {@link ForgeCapabilities#ENERGY} and {@link MjAPI#CAP_CONNECTOR} will be excluded. - */ - private List> getAllHasCapAround(Capability capability) { - return Arrays.stream(Direction.VALUES) - .map(d -> new Pair<>(d, this.worldPosition.relative(d))) - .filter(p -> this.level.getBlockState(p.getSecond()).getBlock() != BCCompatBlocks.powerConvertor.get()) - .map(p -> new Pair<>(p.getFirst(), this.level.getBlockEntity(p.getSecond()))) - .filter(p -> p.getSecond() != null) - // should not have both - .filter(p -> { - Direction dir = p.getFirst(); - BlockEntity te = p.getSecond(); - boolean has_FORGE_ENERGY = te.getCapability(ForgeCapabilities.ENERGY, dir).isPresent(); - boolean has_CAP_CONNECTOR = te.getCapability(MjAPI.CAP_CONNECTOR, dir).isPresent(); - return !(has_FORGE_ENERGY && has_CAP_CONNECTOR); - }) - .map(p -> new Pair<>(p.getFirst(), p.getSecond().getCapability(capability, p.getFirst().getOpposite()))) - .filter(p -> p.getSecond().isPresent()) - .map(p -> new Pair<>(p.getFirst(), p.getSecond().orElse(null))) - .toList(); - } - - public static int convert_mMJ_2_FE(long mMJ) { - return (int) Math.min(Integer.MAX_VALUE, mMJ * 16L / MjAPI.MJ); - } - - public static long convert_FE_2_mMJ(int fe) { - return fe * MjAPI.MJ / 16L; - } -} From 069e82ec399633d08552eecbf08544655f50328f Mon Sep 17 00:00:00 2001 From: CalenXwX Date: Sat, 25 Jan 2025 12:41:15 +0800 Subject: [PATCH 6/9] Updated gitsubmodule --- BuildCraft | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BuildCraft b/BuildCraft index 07d7fcb..10a8267 160000 --- a/BuildCraft +++ b/BuildCraft @@ -1 +1 @@ -Subproject commit 07d7fcb06fcdc89fcd264752c24e0e27446c3e51 +Subproject commit 10a8267e88351d09d0ccea79841f1b21f8970f74 From 7b8aa0ba270296eae3219962b57c7374f86cd8dd Mon Sep 17 00:00:00 2001 From: CalenXwX Date: Sat, 15 Feb 2025 12:17:22 +0800 Subject: [PATCH 7/9] Updated FE engine resources --- BuildCraft | 2 +- build.gradle | 13 +++++++++++-- common/buildcraft/compat/BCCompat.java | 2 -- resources/assets/buildcraftcompat/lang/en_us.json | 2 +- resources/assets/buildcraftcompat/lang/zh_cn.json | 2 +- .../buildcraftcompat/models/tile/engine_fe.jsonbc | 7 +++++++ .../textures/block/engine/fe/back.png | Bin 0 -> 460 bytes .../textures/block/engine/fe/side.png | Bin 0 -> 265 bytes 8 files changed, 21 insertions(+), 7 deletions(-) create mode 100644 resources/assets/buildcraftcompat/models/tile/engine_fe.jsonbc create mode 100644 resources/assets/buildcraftcompat/textures/block/engine/fe/back.png create mode 100644 resources/assets/buildcraftcompat/textures/block/engine/fe/side.png diff --git a/BuildCraft b/BuildCraft index 10a8267..cd39ab0 160000 --- a/BuildCraft +++ b/BuildCraft @@ -1 +1 @@ -Subproject commit 10a8267e88351d09d0ccea79841f1b21f8970f74 +Subproject commit cd39ab0f174e783b05de1934855388a512dfc021 diff --git a/build.gradle b/build.gradle index 0d67f63..2a97398 100755 --- a/build.gradle +++ b/build.gradle @@ -168,10 +168,12 @@ minecraft { data { // example of overriding the workingDirectory set in configureEach above - workingDirectory project.file('run-data') + workingDirectory project.file('run_data') // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. - args '--mod', mod_id, '--all', '--output', file('BuildCraft/buildcraft_resources_generated/'), '--existing', file('BuildCraft/buildcraft_resources/') + args '--mod', mod_id, '--all', '--output', file('BuildCraft/buildcraft_resources_generated/'), + '--existing', file('BuildCraft/buildcraft_resources/'), + '--existing', file('resources/') } } } @@ -519,3 +521,10 @@ tasks.withType(JavaCompile).configureEach { } jar.enabled = true + +// enable Jar-in-Jar +jarJar.enable() + +tasks.named('jarJar') { + // ... +} diff --git a/common/buildcraft/compat/BCCompat.java b/common/buildcraft/compat/BCCompat.java index 35f3605..9af0947 100644 --- a/common/buildcraft/compat/BCCompat.java +++ b/common/buildcraft/compat/BCCompat.java @@ -109,8 +109,6 @@ public static void preInit(FMLConstructModEvent evt) { // Calen BCCompatBlocks.fmlPreInit(); - - // Calen 1.20.1 BCCompatProxy.getProxy().fmlPreInit(); } diff --git a/resources/assets/buildcraftcompat/lang/en_us.json b/resources/assets/buildcraftcompat/lang/en_us.json index 24d3e4d..627dd9c 100644 --- a/resources/assets/buildcraftcompat/lang/en_us.json +++ b/resources/assets/buildcraftcompat/lang/en_us.json @@ -59,7 +59,7 @@ "config.jade.plugin_buildcraftcore.mj_storage_server_data": "MJ Storage", // Calen FE compat - "tile.power_convertor.name": "Power Convertor", + "tile.engineFe.name": "FE Engine", "null": "=w=" } diff --git a/resources/assets/buildcraftcompat/lang/zh_cn.json b/resources/assets/buildcraftcompat/lang/zh_cn.json index 11755c0..3ca27f3 100644 --- a/resources/assets/buildcraftcompat/lang/zh_cn.json +++ b/resources/assets/buildcraftcompat/lang/zh_cn.json @@ -54,7 +54,7 @@ "config.jade.plugin_buildcraftcore.mj_storage_server_data": "MJ存储", // Calen FE compat - "tile.power_convertor.name": "能源转换器", + "tile.engineFe.name": "FE引擎", "null": "=w=" } diff --git a/resources/assets/buildcraftcompat/models/tile/engine_fe.jsonbc b/resources/assets/buildcraftcompat/models/tile/engine_fe.jsonbc new file mode 100644 index 0000000..0b16eaa --- /dev/null +++ b/resources/assets/buildcraftcompat/models/tile/engine_fe.jsonbc @@ -0,0 +1,7 @@ +{ + "textures": { + "#back":"buildcraftcompat:block/engine/fe/back", + "#side":"buildcraftcompat:block/engine/fe/side" + }, + "parent":"buildcraftlib:models/tile/engine_base" +} \ No newline at end of file diff --git a/resources/assets/buildcraftcompat/textures/block/engine/fe/back.png b/resources/assets/buildcraftcompat/textures/block/engine/fe/back.png new file mode 100644 index 0000000000000000000000000000000000000000..06da85225017205de7397d88ff759b3a94821106 GIT binary patch literal 460 zcmV;-0WEj-sCeeS$ouV}3m=N$L@eH4Wd zMzenIU=iW@d;(Bw#R5#zM2wO1`ON>s;cyt=R#gchFijHx`~4nO9U9bHQPlysTrNu; zI)f0x5GJLx0M}YqMFu_^%o&IXA%q2Z&Y;(%l)emJuh(DzkWxZb$vOW8257C}y+=eo z4K|z2;-_;C0OuSzXMmCCm$cTt4A!ELxaS@@=W$j5@BJ{x96Z;czxkJ$cDt_Gw1Y(i z@BNrYHyMEa_4)6d*P`2d7zyC|62=&E&STMfvlt_#ln;YB?Y_EQlYg!8JpKS;V&J`$ec0y!0000 zi-E7Opkwyi1E)7Vco(uaukUdO(+=ykrg!F+#&&YJv~(yKcXBYC$uVb6QJXfC=P<*D z>vvtkukst;E6-oEs`|y!pXPN6{lC}#U^vzOgT2Q2fbgF)xk1+p{#*mPkipZ{&t;uc GLK6U9sb}v1 literal 0 HcmV?d00001 From caa74ca8c1543872c9f377c250e72999ba92107d Mon Sep 17 00:00:00 2001 From: CalenXwX Date: Thu, 24 Apr 2025 14:28:44 +0800 Subject: [PATCH 8/9] Update JEI&REI plugin for robotics recipes, update HWYLA plugin for robot energy and remove FE engine --- .gitignore | 1 + BuildCraft | 2 +- build.gradle | 5 +- common/buildcraft/compat/BCCompat.java | 5 - common/buildcraft/compat/BCCompatBlocks.java | 30 ----- common/buildcraft/compat/BCCompatModels.java | 121 ------------------ common/buildcraft/compat/BCCompatProxy.java | 1 - .../datagen/BCCompatDataGenerators.java | 49 ------- .../datagen/CompatBlockStateGenerator.java | 19 --- .../datagen/CompatItemModelGenerator.java | 19 --- .../forge/BlockEnergyCompatEngine_BC8.java | 15 --- .../forge/EnumEnergyCompatEngineTypes.java | 21 --- .../compat/module/forge/RenderEngineFe.java | 20 --- .../compat/module/forge/TileEngineFe.java | 113 ---------------- .../compat/module/jei/BCPluginJEI.java | 15 +++ .../jei/silicon/CategoryIntegrationTable.java | 45 +++---- .../jei/silicon/CategoryProgrammingTable.java | 108 ++++++++++++++++ .../compat/module/rei/BCPluginREI.java | 14 +- .../rei/silicon/CategoryIntegrationTable.java | 112 +++++++++++++++- .../rei/silicon/CategoryProgrammingTable.java | 109 ++++++++++++++++ .../rei/silicon/DisplayIntegration.java | 18 ++- .../rei/silicon/DisplayProgramming.java | 36 ++++++ .../module/theoneprobe/BCPluginTOP.java | 6 +- .../module/waila/BaseWailaDataProvider.java | 29 ++++- .../compat/module/waila/HWYLAPlugin.java | 5 + .../module/waila/RobotPowerDataProvider.java | 63 +++++++++ .../assets/buildcraftcompat/lang/en_us.json | 5 +- .../assets/buildcraftcompat/lang/zh_cn.json | 5 +- .../models/tile/engine_fe.jsonbc | 7 - .../textures/block/engine/fe/back.png | Bin 460 -> 0 bytes .../textures/block/engine/fe/side.png | Bin 265 -> 0 bytes 31 files changed, 524 insertions(+), 474 deletions(-) delete mode 100644 common/buildcraft/compat/BCCompatBlocks.java delete mode 100644 common/buildcraft/compat/BCCompatModels.java delete mode 100644 common/buildcraft/compat/datagen/BCCompatDataGenerators.java delete mode 100644 common/buildcraft/compat/datagen/CompatBlockStateGenerator.java delete mode 100644 common/buildcraft/compat/datagen/CompatItemModelGenerator.java delete mode 100644 common/buildcraft/compat/module/forge/BlockEnergyCompatEngine_BC8.java delete mode 100644 common/buildcraft/compat/module/forge/EnumEnergyCompatEngineTypes.java delete mode 100644 common/buildcraft/compat/module/forge/RenderEngineFe.java delete mode 100644 common/buildcraft/compat/module/forge/TileEngineFe.java create mode 100644 common/buildcraft/compat/module/jei/silicon/CategoryProgrammingTable.java create mode 100644 common/buildcraft/compat/module/rei/silicon/CategoryProgrammingTable.java create mode 100644 common/buildcraft/compat/module/rei/silicon/DisplayProgramming.java create mode 100644 common/buildcraft/compat/module/waila/RobotPowerDataProvider.java delete mode 100644 resources/assets/buildcraftcompat/models/tile/engine_fe.jsonbc delete mode 100644 resources/assets/buildcraftcompat/textures/block/engine/fe/back.png delete mode 100644 resources/assets/buildcraftcompat/textures/block/engine/fe/side.png diff --git a/.gitignore b/.gitignore index adcedd9..f60b507 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ libs #runtime run run_server +run_data classes #mac diff --git a/BuildCraft b/BuildCraft index cd39ab0..5b2a59e 160000 --- a/BuildCraft +++ b/BuildCraft @@ -1 +1 @@ -Subproject commit cd39ab0f174e783b05de1934855388a512dfc021 +Subproject commit 5b2a59ec97573ef743365a4b1e86eee4fa8f62c8 diff --git a/build.gradle b/build.gradle index 2a97398..cf96f12 100755 --- a/build.gradle +++ b/build.gradle @@ -172,8 +172,7 @@ minecraft { // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. args '--mod', mod_id, '--all', '--output', file('BuildCraft/buildcraft_resources_generated/'), - '--existing', file('BuildCraft/buildcraft_resources/'), - '--existing', file('resources/') + '--existing', file('BuildCraft/buildcraft_resources/') } } } @@ -334,7 +333,7 @@ dependencies { implementation fg.deobf("curse.maven:jade-324717:" + config.jade_id) // CraftTweaker - implementation(fg.deobf('com.blamejared.crafttweaker:CraftTweaker-forge-1.20.1:14.0.44')) + implementation fg.deobf('com.blamejared.crafttweaker:CraftTweaker-forge-1.20.1:14.0.44') // The One Probe implementation fg.deobf("curse.maven:the-one-probe-245211:" + config.top_id) diff --git a/common/buildcraft/compat/BCCompat.java b/common/buildcraft/compat/BCCompat.java index 9af0947..9668a92 100644 --- a/common/buildcraft/compat/BCCompat.java +++ b/common/buildcraft/compat/BCCompat.java @@ -108,7 +108,6 @@ public static void preInit(FMLConstructModEvent evt) { // End of module list // Calen - BCCompatBlocks.fmlPreInit(); BCCompatProxy.getProxy().fmlPreInit(); } @@ -151,10 +150,6 @@ public static void postInit(FMLLoadCompleteEvent evt) { static { startBatch(); - registerTag("item.block.engine.bc.fe").reg("engine_fe").locale("engineFe"); - registerTag("block.engine.bc.fe").reg("engine_fe").locale("engineFe"); - registerTag("tile.engine.fe").reg("engine_fe"); - endBatch(TagManager.prependTags("buildcraftcompat:", TagManager.EnumTagType.REGISTRY_NAME) .andThen(TagManager.setTab("buildcraft.main")) ); diff --git a/common/buildcraft/compat/BCCompatBlocks.java b/common/buildcraft/compat/BCCompatBlocks.java deleted file mode 100644 index ed42cad..0000000 --- a/common/buildcraft/compat/BCCompatBlocks.java +++ /dev/null @@ -1,30 +0,0 @@ -package buildcraft.compat; - -import buildcraft.compat.module.forge.BlockEnergyCompatEngine_BC8; -import buildcraft.compat.module.forge.EnumEnergyCompatEngineTypes; -import buildcraft.compat.module.forge.TileEngineFe; -import buildcraft.core.item.ItemEngine_BC8; -import buildcraft.lib.block.BlockPropertiesCreator; -import buildcraft.lib.registry.RegistrationHelper; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraftforge.registries.RegistryObject; - -public class BCCompatBlocks { - public static final RegistrationHelper HELPER = new RegistrationHelper(BCCompat.MODID); - public static final RegistryObject engineFe; - public static final RegistryObject> engineFeTile; - - static { - engineFe = HELPER.addBlockAndItem("block.engine.bc." + EnumEnergyCompatEngineTypes.FE.getSerializedName(), - BlockPropertiesCreator.metal() - .strength(5.0F, 10.0F) - .sound(SoundType.METAL) - .noOcclusion() - , (idBC, properties) -> new BlockEnergyCompatEngine_BC8(idBC, properties, EnumEnergyCompatEngineTypes.FE, TileEngineFe::new), ItemEngine_BC8::new); - engineFeTile = HELPER.registerTile("tile.engine.fe", TileEngineFe::new, engineFe); - } - - public static void fmlPreInit() { - } -} diff --git a/common/buildcraft/compat/BCCompatModels.java b/common/buildcraft/compat/BCCompatModels.java deleted file mode 100644 index c12cc4d..0000000 --- a/common/buildcraft/compat/BCCompatModels.java +++ /dev/null @@ -1,121 +0,0 @@ -package buildcraft.compat; - -import buildcraft.api.enums.EnumPowerStage; -import buildcraft.compat.module.forge.EnumEnergyCompatEngineTypes; -import buildcraft.compat.module.forge.RenderEngineFe; -import buildcraft.compat.module.forge.TileEngineFe; -import buildcraft.core.block.BlockEngine_BC8; -import buildcraft.lib.client.model.ModelHolderVariable; -import buildcraft.lib.client.model.ModelItemSimple; -import buildcraft.lib.client.model.MutableQuad; -import buildcraft.lib.engine.TileEngineBase_BC8; -import buildcraft.lib.expression.DefaultContexts; -import buildcraft.lib.expression.FunctionContext; -import buildcraft.lib.expression.node.value.NodeVariableDouble; -import buildcraft.lib.expression.node.value.NodeVariableObject; -import buildcraft.lib.misc.ExpressionCompat; -import buildcraft.lib.misc.data.ModelVariableData; -import com.google.common.collect.Lists; -import net.minecraft.client.renderer.blockentity.BlockEntityRenderers; -import net.minecraft.client.renderer.texture.TextureAtlas; -import net.minecraft.client.resources.model.ModelResourceLocation; -import net.minecraft.core.Direction; -import net.minecraft.util.LazyLoadedValue; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.client.event.EntityRenderersEvent; -import net.minecraftforge.client.event.ModelEvent; -import net.minecraftforge.client.event.TextureStitchEvent; -import net.minecraftforge.eventbus.api.IEventBus; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.ModList; -import net.minecraftforge.fml.javafmlmod.FMLModContainer; - -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -@OnlyIn(Dist.CLIENT) -public class BCCompatModels { - private static final NodeVariableDouble ENGINE_PROGRESS; - private static final NodeVariableObject ENGINE_STAGE; - private static final NodeVariableObject ENGINE_FACING; - - private static final ModelHolderVariable ENGINE_FE; - - static { - FunctionContext fnCtx = new FunctionContext(ExpressionCompat.ENUM_POWER_STAGE, DefaultContexts.createWithAll()); - ENGINE_PROGRESS = fnCtx.putVariableDouble("progress"); - ENGINE_STAGE = fnCtx.putVariableObject("stage", EnumPowerStage.class); - ENGINE_FACING = fnCtx.putVariableObject("direction", Direction.class); - // TODO: Item models from "item/engine_stone.json" - ENGINE_FE = new ModelHolderVariable( - "buildcraftcompat:models/tile/engine_fe.jsonbc", - fnCtx - ); - BlockEngine_BC8.setModel(EnumEnergyCompatEngineTypes.FE, ENGINE_FE); - } - - public static void fmlPreInit() { - // 1.18.2: following events are IModBusEvent - IEventBus modEventBus = ((FMLModContainer) ModList.get().getModContainerById(BCCompat.MODID).get()).getEventBus(); - modEventBus.register(BCCompatModels.class); - } - - @SubscribeEvent - public static void onTesrReg(EntityRenderersEvent.RegisterRenderers event) { - BlockEntityRenderers.register(BCCompatBlocks.engineFeTile.get(), RenderEngineFe::new); - } - - // Calen 1.20.1 - private static final List spriteTasks = Lists.newLinkedList(); - - // Calen 1.20.1 - @SubscribeEvent - public static void onTextureStitchEvent$Post(TextureStitchEvent.Post event) { - if (event.getAtlas().location().equals(TextureAtlas.LOCATION_BLOCKS)) { - spriteTasks.forEach(Runnable::run); - } - } - - @SubscribeEvent - public static void onModelBake(ModelEvent.ModifyBakingResult event) { - ENGINE_PROGRESS.value = 0.2; - ENGINE_STAGE.value = EnumPowerStage.BLUE; - ENGINE_FACING.value = Direction.UP; - ModelVariableData varData = new ModelVariableData(); - varData.setNodes(ENGINE_FE.createTickableNodes()); - varData.tick(); - varData.refresh(); - event.getModels().put( - new ModelResourceLocation(BCCompatBlocks.engineFe.getId(), "inventory"), - new ModelItemSimple( - new LazyLoadedValue<>( - () -> Arrays.stream(ENGINE_FE.getCutoutQuads()) - .map(MutableQuad::toBakedItem) - .collect(Collectors.toList()) - ), - ModelItemSimple.TRANSFORM_BLOCK, - true, - spriteTasks::add - ) - ); - } - - private static MutableQuad[] getEngineQuads(ModelHolderVariable model, - TileEngineBase_BC8 tile, - float partialTicks) { - ENGINE_PROGRESS.value = tile.getProgressClient(partialTicks); - ENGINE_STAGE.value = tile.getPowerStage(); - ENGINE_FACING.value = tile.getCurrentFacing(); - if (tile.clientModelData.hasNoNodes()) { - tile.clientModelData.setNodes(model.createTickableNodes()); - } - tile.clientModelData.refresh(); - return model.getCutoutQuads(); - } - - public static MutableQuad[] getFeEngineQuads(TileEngineFe tile, float partialTicks) { - return getEngineQuads(ENGINE_FE, tile, partialTicks); - } -} diff --git a/common/buildcraft/compat/BCCompatProxy.java b/common/buildcraft/compat/BCCompatProxy.java index 53d6419..9c947a4 100644 --- a/common/buildcraft/compat/BCCompatProxy.java +++ b/common/buildcraft/compat/BCCompatProxy.java @@ -36,7 +36,6 @@ public static class ClientProxy extends BCCompatProxy { @Override public void fmlPreInit() { super.fmlPreInit(); - BCCompatModels.fmlPreInit(); } } } diff --git a/common/buildcraft/compat/datagen/BCCompatDataGenerators.java b/common/buildcraft/compat/datagen/BCCompatDataGenerators.java deleted file mode 100644 index 6dff9db..0000000 --- a/common/buildcraft/compat/datagen/BCCompatDataGenerators.java +++ /dev/null @@ -1,49 +0,0 @@ -package buildcraft.compat.datagen; - -import buildcraft.api.core.BCLog; -import buildcraft.core.BCCore; -import net.minecraft.data.DataGenerator; -import net.minecraftforge.common.data.ExistingFileHelper; -import net.minecraftforge.data.event.GatherDataEvent; -import net.minecraftforge.data.loading.DatagenModLoader; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; - -import java.lang.reflect.Field; -import java.util.List; - -@Mod.EventBusSubscriber(modid = BCCore.MODID, bus = Mod.EventBusSubscriber.Bus.MOD) -public class BCCompatDataGenerators { - @SubscribeEvent - public static void onGatherData(GatherDataEvent event) { - DataGenerator generator = event.getGenerator(); - ExistingFileHelper existingFileHelper = event.getExistingFileHelper(); - DataGenerator.PackGenerator packGenerator = generator.getVanillaPack(true); - - // BlockState and Block Model - packGenerator.addProvider(packOutput -> new CompatBlockStateGenerator(packOutput, existingFileHelper)); - - // Item Model - packGenerator.addProvider(packOutput -> new CompatItemModelGenerator(packOutput, existingFileHelper)); - - // Calen 1.20.1 - enableShouldExecute(generator); - } - - // Calen 1.20.1 for datagen - private static void enableShouldExecute(DataGenerator generator) { - try { - Field f_dataGeneratorConfig = DatagenModLoader.class.getDeclaredField("dataGeneratorConfig"); - f_dataGeneratorConfig.setAccessible(true); - GatherDataEvent.DataGeneratorConfig config = (GatherDataEvent.DataGeneratorConfig) f_dataGeneratorConfig.get(null); - Field f_generators = GatherDataEvent.DataGeneratorConfig.class.getDeclaredField("generators"); - f_generators.setAccessible(true); - List generators = (List) f_generators.get(config); - if (!generators.contains(generator)) { - generators.add(generator); - } - } catch (Exception e) { - BCLog.logger.error(e); - } - } -} diff --git a/common/buildcraft/compat/datagen/CompatBlockStateGenerator.java b/common/buildcraft/compat/datagen/CompatBlockStateGenerator.java deleted file mode 100644 index 7c6374b..0000000 --- a/common/buildcraft/compat/datagen/CompatBlockStateGenerator.java +++ /dev/null @@ -1,19 +0,0 @@ -package buildcraft.compat.datagen; - -import buildcraft.compat.BCCompat; -import buildcraft.compat.BCCompatBlocks; -import buildcraft.datagen.base.BCBaseBlockStateGenerator; -import net.minecraft.data.PackOutput; -import net.minecraftforge.common.data.ExistingFileHelper; - -public class CompatBlockStateGenerator extends BCBaseBlockStateGenerator { - public CompatBlockStateGenerator(PackOutput output, ExistingFileHelper exFileHelper) { - super(output, BCCompat.MODID, exFileHelper); - } - - @Override - protected void registerStatesAndModels() { - // fe engine - builtinEntity(BCCompatBlocks.engineFe.get(), "buildcraftcompat:block/engine/fe/back"); - } -} diff --git a/common/buildcraft/compat/datagen/CompatItemModelGenerator.java b/common/buildcraft/compat/datagen/CompatItemModelGenerator.java deleted file mode 100644 index cba884b..0000000 --- a/common/buildcraft/compat/datagen/CompatItemModelGenerator.java +++ /dev/null @@ -1,19 +0,0 @@ -package buildcraft.compat.datagen; - -import buildcraft.compat.BCCompat; -import buildcraft.compat.BCCompatBlocks; -import buildcraft.datagen.base.BCBaseItemModelGenerator; -import net.minecraft.data.PackOutput; -import net.minecraftforge.common.data.ExistingFileHelper; - -public class CompatItemModelGenerator extends BCBaseItemModelGenerator { - public CompatItemModelGenerator(PackOutput output, ExistingFileHelper existingFileHelper) { - super(output, BCCompat.MODID, existingFileHelper); - } - - @Override - protected void registerModels() { - // fe engine - getBuilder(BCCompatBlocks.engineFe.get().getRegistryName().toString()).parent(BUILTIN_ENTITY); - } -} diff --git a/common/buildcraft/compat/module/forge/BlockEnergyCompatEngine_BC8.java b/common/buildcraft/compat/module/forge/BlockEnergyCompatEngine_BC8.java deleted file mode 100644 index 8197654..0000000 --- a/common/buildcraft/compat/module/forge/BlockEnergyCompatEngine_BC8.java +++ /dev/null @@ -1,15 +0,0 @@ -package buildcraft.compat.module.forge; - -import buildcraft.lib.engine.BlockEngineBase_BC8; -import buildcraft.lib.engine.TileEngineBase_BC8; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.block.state.BlockState; - -import java.util.function.BiFunction; - -public class BlockEnergyCompatEngine_BC8 extends BlockEngineBase_BC8 { - public BlockEnergyCompatEngine_BC8(String idBC, BlockBehaviour.Properties properties, EnumEnergyCompatEngineTypes type, BiFunction engineTileConstructor) { - super(idBC, properties, type, engineTileConstructor); - } -} diff --git a/common/buildcraft/compat/module/forge/EnumEnergyCompatEngineTypes.java b/common/buildcraft/compat/module/forge/EnumEnergyCompatEngineTypes.java deleted file mode 100644 index a1053b2..0000000 --- a/common/buildcraft/compat/module/forge/EnumEnergyCompatEngineTypes.java +++ /dev/null @@ -1,21 +0,0 @@ -package buildcraft.compat.module.forge; - -import buildcraft.api.core.IEngineType; -import net.minecraft.util.StringRepresentable; - -public enum EnumEnergyCompatEngineTypes implements StringRepresentable, IEngineType { - FE("compat", "fe"); - - public static final EnumEnergyCompatEngineTypes[] VALUES = values(); - - public final String unlocalizedTag; - - EnumEnergyCompatEngineTypes(String mod, String loc) { - unlocalizedTag = loc; - } - - @Override - public String getSerializedName() { - return unlocalizedTag; - } -} diff --git a/common/buildcraft/compat/module/forge/RenderEngineFe.java b/common/buildcraft/compat/module/forge/RenderEngineFe.java deleted file mode 100644 index 8bef1b2..0000000 --- a/common/buildcraft/compat/module/forge/RenderEngineFe.java +++ /dev/null @@ -1,20 +0,0 @@ -package buildcraft.compat.module.forge; - -import buildcraft.compat.BCCompatModels; -import buildcraft.lib.client.model.MutableQuad; -import buildcraft.lib.client.render.tile.RenderEngine_BC8; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -@OnlyIn(Dist.CLIENT) -public class RenderEngineFe extends RenderEngine_BC8 { - public RenderEngineFe(BlockEntityRendererProvider.Context context) { - super(context); - } - - @Override - protected MutableQuad[] getEngineModel(TileEngineFe engine, float partialTicks) { - return BCCompatModels.getFeEngineQuads(engine, partialTicks); - } -} diff --git a/common/buildcraft/compat/module/forge/TileEngineFe.java b/common/buildcraft/compat/module/forge/TileEngineFe.java deleted file mode 100644 index bfb0c90..0000000 --- a/common/buildcraft/compat/module/forge/TileEngineFe.java +++ /dev/null @@ -1,113 +0,0 @@ -package buildcraft.compat.module.forge; - -import buildcraft.api.core.EnumPipePart; -import buildcraft.api.enums.EnumPowerStage; -import buildcraft.api.mj.IMjConnector; -import buildcraft.api.mj.MjAPI; -import buildcraft.compat.BCCompatBlocks; -import buildcraft.lib.engine.EngineConnector; -import buildcraft.lib.engine.TileEngineBase_BC8; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.common.capabilities.ForgeCapabilities; -import net.minecraftforge.energy.IEnergyStorage; -import org.jetbrains.annotations.NotNull; - -public class TileEngineFe extends TileEngineBase_BC8 { - private static final int MJ_CAP = 10_000; - private static final int FE_CAP = convert_mMJ_2_FE(MJ_CAP * MjAPI.MJ); - - private final IEnergyStorage feStorage = new IEnergyStorage() { - @Override - public int receiveEnergy(int maxReceive, boolean simulate) { - int received_FE = Math.min(convert_mMJ_2_FE(TileEngineFe.this.getMaxPower() - TileEngineFe.this.getEnergyStored()), maxReceive); - if (!simulate) { - addPower(convert_FE_2_mMJ(received_FE)); - } - return received_FE; - } - - @Override - public int extractEnergy(int maxExtract, boolean simulate) { - return 0; - } - - @Override - public int getEnergyStored() { - return convert_mMJ_2_FE(TileEngineFe.this.getEnergyStored()); - } - - @Override - public int getMaxEnergyStored() { - return FE_CAP; - } - - @Override - public boolean canExtract() { - return false; - } - - @Override - public boolean canReceive() { - return true; - } - }; - - public TileEngineFe(BlockPos pos, BlockState blockState) { - super(BCCompatBlocks.engineFeTile.get(), pos, blockState); - caps.addCapabilityInstance(ForgeCapabilities.ENERGY, this.feStorage, EnumPipePart.VALUES); - } - - @NotNull - @Override - protected IMjConnector createConnector() { - return new EngineConnector(false); - } - - @Override - public boolean isBurning() { - return isRedstonePowered; - } - - @Override - public long getMaxPower() { - return MJ_CAP * MjAPI.MJ; - } - - @Override - public long maxPowerReceived() { - return 2_000 * MjAPI.MJ; - } - - @Override - public long maxPowerExtracted() { - return 1_000 * MjAPI.MJ; - } - - @Override - public float explosionRange() { - return 0; - } - - @Override - public long getCurrentOutput() { - return 256 * MjAPI.MJ; - } - - @Override - protected EnumPowerStage computePowerStage() { - return EnumPowerStage.RED; - } - - @Override - protected void burn() { - } - - public static int convert_mMJ_2_FE(long mMJ) { - return (int) Math.min(Integer.MAX_VALUE, mMJ * 16L / MjAPI.MJ); - } - - public static long convert_FE_2_mMJ(int fe) { - return fe * MjAPI.MJ / 16L; - } -} diff --git a/common/buildcraft/compat/module/jei/BCPluginJEI.java b/common/buildcraft/compat/module/jei/BCPluginJEI.java index b4b6e13..5416030 100644 --- a/common/buildcraft/compat/module/jei/BCPluginJEI.java +++ b/common/buildcraft/compat/module/jei/BCPluginJEI.java @@ -4,7 +4,9 @@ import buildcraft.api.core.BCLog; import buildcraft.api.enums.EnumEngineType; import buildcraft.api.fuels.IFuel; +import buildcraft.api.recipes.IProgrammingRecipe; import buildcraft.api.recipes.IRefineryRecipeManager; +import buildcraft.api.recipes.IntegrationRecipe; import buildcraft.compat.BCCompatConfig; import buildcraft.compat.module.jei.energy.combustionengine.CategoryCombustionEngine; import buildcraft.compat.module.jei.factory.CategoryCoolable; @@ -13,6 +15,8 @@ import buildcraft.compat.module.jei.gui.GuiGhostIngredientHandlerBuildCraft; import buildcraft.compat.module.jei.gui.GuiHandlerBuildCraft; import buildcraft.compat.module.jei.silicon.CategoryAssemblyTable; +import buildcraft.compat.module.jei.silicon.CategoryIntegrationTable; +import buildcraft.compat.module.jei.silicon.CategoryProgrammingTable; import buildcraft.compat.module.jei.transferhandlers.AdvancedCraftingItemsTransferHandler; import buildcraft.compat.module.jei.transferhandlers.AutoCraftItemsTransferHandler; import buildcraft.core.BCCoreBlocks; @@ -24,10 +28,13 @@ import buildcraft.lib.recipe.assembly.AssemblyRecipe; import buildcraft.lib.recipe.assembly.AssemblyRecipeRegistry; import buildcraft.lib.recipe.fuel.FuelRegistry; +import buildcraft.lib.recipe.programming.ProgrammingRecipeManager; import buildcraft.silicon.BCSiliconBlocks; import buildcraft.silicon.BCSiliconItems; import buildcraft.silicon.BCSiliconMenuTypes; import buildcraft.silicon.container.ContainerAssemblyTable; +import buildcraft.silicon.container.ContainerIntegrationTable; +import buildcraft.silicon.container.ContainerProgrammingTable_Neptune; import buildcraft.transport.BCTransportItems; import buildcraft.transport.pipe.PipeRegistry; import com.google.common.collect.ImmutableList; @@ -104,6 +111,8 @@ public void registerRecipes(IRecipeRegistration registry) { // 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(CategoryAssemblyTable.RECIPE_TYPE, ImmutableList.copyOf(Minecraft.getInstance().level.getRecipeManager().getAllRecipesFor(AssemblyRecipe.TYPE))); + registry.addRecipes(CategoryIntegrationTable.RECIPE_TYPE, ImmutableList.copyOf(Minecraft.getInstance().level.getRecipeManager().getAllRecipesFor(IntegrationRecipe.TYPE))); + registry.addRecipes(CategoryProgrammingTable.RECIPE_TYPE, ImmutableList.copyOf(Minecraft.getInstance().level.getRecipeManager().getAllRecipesFor(IProgrammingRecipe.TYPE))); } } @@ -117,6 +126,8 @@ public void registerRecipeTransferHandlers(IRecipeTransferRegistration registry) registry.addRecipeTransferHandler(new AdvancedCraftingItemsTransferHandler(), RecipeTypes.CRAFTING); // registry.addRecipeTransferHandler(ContainerAssemblyTable.class, "buildcraft-compat:silicon.assembly", 36, 12, 0, 36); registry.addRecipeTransferHandler(ContainerAssemblyTable.class, BCSiliconMenuTypes.ASSEMBLY_TABLE, CategoryAssemblyTable.RECIPE_TYPE, 36, 12, 0, 36); + registry.addRecipeTransferHandler(ContainerIntegrationTable.class, BCSiliconMenuTypes.INTEGRATION_TABLE, CategoryIntegrationTable.RECIPE_TYPE, 36, 11, 0, 36); + registry.addRecipeTransferHandler(ContainerProgrammingTable_Neptune.class, BCSiliconMenuTypes.PROGRAMMING_TABLE, CategoryProgrammingTable.RECIPE_TYPE, 36, 26, 0, 36); } @Override @@ -146,6 +157,8 @@ public void registerCategories(IRecipeCategoryRegistration registry) { lst.add("silicon"); // registry.addRecipeCategories(new IRecipeCategory[]{new CategoryAssemblyTable(helper)}); registry.addRecipeCategories(new IRecipeCategory[] { new CategoryAssemblyTable(helper, AssemblyRecipeRegistry.getAll(Minecraft.getInstance().level)) }); + registry.addRecipeCategories(new IRecipeCategory[] { new CategoryIntegrationTable(helper) }); + registry.addRecipeCategories(new IRecipeCategory[] { new CategoryProgrammingTable(helper, ProgrammingRecipeManager.INSTANCE.getRecipes(Minecraft.getInstance().level)) }); } BCLog.logger.info("Loaded JEI mods: " + Arrays.toString(lst.toArray())); @@ -198,6 +211,8 @@ public void registerRecipeCatalysts(IRecipeCatalystRegistration registry) { 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.RECIPE_TYPE); + registry.addRecipeCatalyst(new ItemStack(BCSiliconBlocks.integrationTable.get()), CategoryIntegrationTable.RECIPE_TYPE); + registry.addRecipeCatalyst(new ItemStack(BCSiliconBlocks.programmingTable.get()), CategoryProgrammingTable.RECIPE_TYPE); } if (BCSiliconBlocks.advancedCraftingTable != null) { diff --git a/common/buildcraft/compat/module/jei/silicon/CategoryIntegrationTable.java b/common/buildcraft/compat/module/jei/silicon/CategoryIntegrationTable.java index 191ed32..759ebe6 100644 --- a/common/buildcraft/compat/module/jei/silicon/CategoryIntegrationTable.java +++ b/common/buildcraft/compat/module/jei/silicon/CategoryIntegrationTable.java @@ -2,10 +2,9 @@ import buildcraft.api.BCModules; import buildcraft.api.mj.MjAPI; +import buildcraft.api.recipes.IngredientStack; import buildcraft.api.recipes.IntegrationRecipe; import buildcraft.silicon.BCSiliconBlocks; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; import mezz.jei.api.gui.drawable.IDrawable; @@ -24,7 +23,6 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.world.level.block.Blocks; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -43,28 +41,19 @@ public class CategoryIntegrationTable implements IRecipeCategory inputs; - private final List outputs; @OnlyIn(Dist.CLIENT) private Font font = Minecraft.getInstance().font; - public CategoryIntegrationTable(IGuiHelper guiHelper, IntegrationRecipe recipe) { + public CategoryIntegrationTable(IGuiHelper guiHelper) { // 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.background = guiHelper.drawableBuilder(this.backgroundLocation, 17, 21, 153, 72).addPadding(0, 0, 9, 0).build(); this.icon = guiHelper.createDrawableIngredient(VanillaTypes.ITEM_STACK, 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(); + IDrawableStatic progressDrawable = guiHelper.drawableBuilder(this.backgroundLocation, 176, 0, 4, 70).addPadding(0, 0, 0, 0).build(); this.progressBar = guiHelper.createAnimatedDrawable(progressDrawable, 720, IDrawableAnimated.StartDirection.BOTTOM, false); } @@ -91,12 +80,11 @@ public IDrawable getIcon() { return this.icon; } - @OnlyIn(Dist.CLIENT) @Override public void draw(IntegrationRecipe recipe, IRecipeSlotsView recipeSlotsView, GuiGraphics guiGraphics, double mouseX, double mouseY) { this.progressBar.draw(guiGraphics, 156, 1); - guiGraphics.drawString(this.font, MjAPI.formatMj(0L) + " MJ", 80, 52, Color.gray.getRGB()); + guiGraphics.drawString(this.font, MjAPI.formatMj(recipe.getRequiredMicroJoules()) + " MJ", 80, 52, Color.gray.getRGB(), false); } @@ -107,16 +95,24 @@ public void setRecipe(IRecipeLayoutBuilder builder, IntegrationRecipe recipe, IF // List> inputs = ingredients.getInputs(ItemStack.class); // int inventoryIndex = 0; + List inputs = recipe.getRequirements(); 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; - if (inputs.size() > slotIndex) { +// int slotIndex = x == 1 && y == 1 ? 0 : x + y * 3 + 1; + if (x == 1 && y == 1) { + builder + .addSlot(RecipeIngredientRole.INPUT, 11 + x * 25, 3 + y * 25) + .addIngredients(recipe.getCenterStack().ingredient); + } else { + int requirementsIndex = (x + y * 3 < 4) ? (x + y * 3) : (x + y * 3 - 1); + if (requirementsIndex < inputs.size()) { // guiItemStacks.init(inventoryIndex, true, 19 + x * 25, 24 + y * 25); // guiItemStacks.set(inventoryIndex, (List) inputs.get(slotIndex)); - builder - .addSlot(RecipeIngredientRole.INPUT, 19 + x * 25, 24 + y * 25) - .addIngredient(VanillaTypes.ITEM_STACK, this.inputs.get(slotIndex)); + builder + .addSlot(RecipeIngredientRole.INPUT, 11 + x * 25, 3 + y * 25) + .addIngredients(inputs.get(requirementsIndex).ingredient); // ++inventoryIndex; + } } } } @@ -124,8 +120,7 @@ public void setRecipe(IRecipeLayoutBuilder builder, IntegrationRecipe recipe, IF // guiItemStacks.init(inventoryIndex, false, 129, 26); // guiItemStacks.set(inventoryIndex, (List) ingredients.getOutputs(ItemStack.class).get(0)); builder - .addSlot(RecipeIngredientRole.INPUT, 129, 26) - .addIngredients(Ingredient.of(this.outputs.stream())); -// ++inventoryIndex; + .addSlot(RecipeIngredientRole.OUTPUT, 130, 28) + .addIngredients(Ingredient.of(recipe.getExampleOutput())); } } diff --git a/common/buildcraft/compat/module/jei/silicon/CategoryProgrammingTable.java b/common/buildcraft/compat/module/jei/silicon/CategoryProgrammingTable.java new file mode 100644 index 0000000..fcf4d19 --- /dev/null +++ b/common/buildcraft/compat/module/jei/silicon/CategoryProgrammingTable.java @@ -0,0 +1,108 @@ +package buildcraft.compat.module.jei.silicon; + +import buildcraft.api.BCModules; +import buildcraft.api.mj.MjAPI; +import buildcraft.api.recipes.IProgrammingRecipe; +import buildcraft.silicon.BCSiliconBlocks; +import mezz.jei.api.constants.VanillaTypes; +import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; +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.IRecipeSlotsView; +import mezz.jei.api.helpers.IGuiHelper; +import mezz.jei.api.recipe.IFocusGroup; +import mezz.jei.api.recipe.RecipeIngredientRole; +import mezz.jei.api.recipe.RecipeType; +import mezz.jei.api.recipe.category.IRecipeCategory; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +import java.awt.*; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +public class CategoryProgrammingTable implements IRecipeCategory { + public static final RecipeType RECIPE_TYPE = + RecipeType.create(BCModules.SILICON.getModId(), "programming", IProgrammingRecipe.class); + public static final ResourceLocation UID = new ResourceLocation(BCModules.SILICON.getModId(), "programming"); + protected final ResourceLocation backgroundLocation = new ResourceLocation("buildcraftsilicon", "textures/gui/programming_table.png"); + private final IDrawable background; + private final IDrawable inputSlot; + private final IDrawable outputSlot; + private final IDrawable arrow; + private final IDrawable progressBarBackground; + private final IDrawableAnimated defaultProgressBar; + private final Map progressBarMap = new HashMap<>(); + private final IDrawable icon; + @OnlyIn(Dist.CLIENT) + private Font font = Minecraft.getInstance().font; + + public CategoryProgrammingTable(IGuiHelper guiHelper, Collection recipes) { + this.background = guiHelper.createBlankDrawable(72, 72); + this.inputSlot = guiHelper.drawableBuilder(this.backgroundLocation, 7, 35, 18, 18).build(); + this.outputSlot = guiHelper.drawableBuilder(this.backgroundLocation, 7, 89, 18, 18).build(); + this.arrow = guiHelper.drawableBuilder(this.backgroundLocation, 28, 40, 11, 8).build(); + this.progressBarBackground = guiHelper.drawableBuilder(this.backgroundLocation, 163, 35, 6, 72).build(); + + this.icon = guiHelper.createDrawableIngredient(VanillaTypes.ITEM_STACK, new ItemStack(BCSiliconBlocks.programmingTable.get())); + + IDrawableStatic progressDrawable = guiHelper.drawableBuilder(this.backgroundLocation, 176, 18, 4, 70).addPadding(0, 0, 0, 0).build(); + this.defaultProgressBar = guiHelper.createAnimatedDrawable(progressDrawable, 720, IDrawableAnimated.StartDirection.BOTTOM, false); + for (IProgrammingRecipe recipe : recipes) { + long mj = recipe.getEnergyCost(); + progressBarMap.put(mj, guiHelper.createAnimatedDrawable(progressDrawable, (int) Math.max(10L, mj / MjAPI.MJ / 50L), IDrawableAnimated.StartDirection.BOTTOM, false)); + } + } + + @Override + public RecipeType getRecipeType() { + return RECIPE_TYPE; + } + + @Override + public Component getTitle() { + return Component.translatable("tile.programmingTableBlock.name"); + } + + @Override + public IDrawable getBackground() { + return background; + } + + @Override + public IDrawable getIcon() { + return this.icon; + } + + @OnlyIn(Dist.CLIENT) + @Override + public void draw(IProgrammingRecipe recipe, IRecipeSlotsView recipeSlotsView, GuiGraphics guiGraphics, double mouseX, double mouseY) { + this.inputSlot.draw(guiGraphics, 2, 27); + this.arrow.draw(guiGraphics, 2 + 18 + 5, 27 + 5); + this.outputSlot.draw(guiGraphics, 2 + 18 + 5 + 11 + 5, 27); + this.progressBarBackground.draw(guiGraphics, 66, 0); + this.progressBarMap.getOrDefault(recipe.getEnergyCost(), this.defaultProgressBar).draw(guiGraphics, 67, 1); + long mj = recipe.getEnergyCost(); + guiGraphics.drawString(font, MjAPI.formatMj(mj) + " MJ", 10, 30 + 5 + 8 + 10, Color.gray.getRGB(), false); + } + + @Override + public void setRecipe(IRecipeLayoutBuilder builder, IProgrammingRecipe recipe, IFocusGroup focuses) { + builder + .addSlot(RecipeIngredientRole.INPUT, 2 + 1, 27 + 1) + .addIngredients(recipe.getInput().ingredient); + + builder + .addSlot(RecipeIngredientRole.OUTPUT, 2 + 18 + 5 + 11 + 5 + 1, 27 + 1) + .addIngredients(Ingredient.of(recipe.getOutput())); + } +} diff --git a/common/buildcraft/compat/module/rei/BCPluginREI.java b/common/buildcraft/compat/module/rei/BCPluginREI.java index edf317b..1b3bdad 100644 --- a/common/buildcraft/compat/module/rei/BCPluginREI.java +++ b/common/buildcraft/compat/module/rei/BCPluginREI.java @@ -4,15 +4,16 @@ import buildcraft.api.core.BCLog; import buildcraft.api.fuels.IFuel; import buildcraft.api.recipes.IAssemblyRecipe; +import buildcraft.api.recipes.IProgrammingRecipe; import buildcraft.api.recipes.IRefineryRecipeManager; +import buildcraft.api.recipes.IntegrationRecipe; import buildcraft.compat.BCCompatConfig; import buildcraft.compat.module.rei.energy.combustionengine.CategoryCombustionEngine; import buildcraft.compat.module.rei.energy.combustionengine.DisplayCombustionEngine; import buildcraft.compat.module.rei.factory.*; import buildcraft.compat.module.rei.gui.GuiGhostIngredientHandlerBuildCraft; import buildcraft.compat.module.rei.gui.GuiHandlerBuildCraft; -import buildcraft.compat.module.rei.silicon.CategoryAssemblyTable; -import buildcraft.compat.module.rei.silicon.DisplayAssembly; +import buildcraft.compat.module.rei.silicon.*; import buildcraft.core.BCCoreItems; import buildcraft.factory.BCFactoryBlocks; import buildcraft.lib.gui.GuiBC8; @@ -30,7 +31,6 @@ import me.shedaniel.rei.api.common.util.EntryStacks; import me.shedaniel.rei.forge.REIPluginClient; import me.shedaniel.rei.plugin.common.BuiltinPlugin; -import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraftforge.fml.ModList; @@ -67,7 +67,11 @@ public void registerCategories(CategoryRegistry registry) { if (silicon) { lst.add("silicon"); registry.add(CategoryAssemblyTable.INSTANCE); + registry.add(CategoryIntegrationTable.INSTANCE); + registry.add(CategoryProgrammingTable.INSTANCE); registry.addWorkstations(CategoryAssemblyTable.ID, CategoryAssemblyTable.ICON); + registry.addWorkstations(CategoryIntegrationTable.ID, CategoryIntegrationTable.ICON); + registry.addWorkstations(CategoryProgrammingTable.ID, CategoryProgrammingTable.ICON); registry.addWorkstations(BuiltinPlugin.CRAFTING, EntryStacks.of(new ItemStack(BCSiliconBlocks.advancedCraftingTable.get()))); } @@ -82,6 +86,8 @@ public void registerDisplays(DisplayRegistry registry) { registry.registerRecipeFiller(IRefineryRecipeManager.ICoolableRecipe.class, IRefineryRecipeManager.ICoolableRecipe.TYPE, DisplayCoolable::new); registry.registerRecipeFiller(IFuel.class, IFuel.TYPE, DisplayCombustionEngine::new); registry.registerRecipeFiller(IAssemblyRecipe.class, IAssemblyRecipe.TYPE, DisplayAssembly::new); + registry.registerRecipeFiller(IntegrationRecipe.class, IntegrationRecipe.TYPE, DisplayIntegration::new); + registry.registerRecipeFiller(IProgrammingRecipe.class, IProgrammingRecipe.TYPE, DisplayProgramming::new); } @Override @@ -99,7 +105,7 @@ public void registerEntries(EntryRegistry registry) { return true; } else if (item instanceof ItemPipeHolder pipe) { if (!BCCompatConfig.coloredPipesVisible) { - if (pipe.getColour() != DyeColor.WHITE) { + if (pipe.getColour() != null) { return true; } } diff --git a/common/buildcraft/compat/module/rei/silicon/CategoryIntegrationTable.java b/common/buildcraft/compat/module/rei/silicon/CategoryIntegrationTable.java index c812461..c69cf96 100644 --- a/common/buildcraft/compat/module/rei/silicon/CategoryIntegrationTable.java +++ b/common/buildcraft/compat/module/rei/silicon/CategoryIntegrationTable.java @@ -1,4 +1,114 @@ package buildcraft.compat.module.rei.silicon; -public class CategoryIntegrationTable { +import buildcraft.api.BCModules; +import buildcraft.api.mj.MjAPI; +import buildcraft.compat.module.rei.ReiUtils; +import buildcraft.silicon.BCSiliconBlocks; +import com.google.common.collect.Lists; +import com.mojang.blaze3d.vertex.PoseStack; +import me.shedaniel.math.Point; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.gui.Renderer; +import me.shedaniel.rei.api.client.gui.widgets.Widget; +import me.shedaniel.rei.api.client.gui.widgets.Widgets; +import me.shedaniel.rei.api.client.registry.display.DisplayCategory; +import me.shedaniel.rei.api.common.category.CategoryIdentifier; +import me.shedaniel.rei.api.common.entry.EntryIngredient; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.util.EntryStacks; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; + +import java.awt.*; +import java.util.List; + +public enum CategoryIntegrationTable implements DisplayCategory { + INSTANCE; + + public static final CategoryIdentifier ID = CategoryIdentifier.of(new ResourceLocation(BCModules.SILICON.getModId(), "category_integration")); + public static final EntryStack ICON = EntryStacks.of(new ItemStack(BCSiliconBlocks.integrationTable.get())); + public static final ResourceLocation BACKGROUND = new ResourceLocation(BCModules.SILICON.getModId(), "textures/gui/integration_table.png"); + + @Override + public CategoryIdentifier getCategoryIdentifier() { + return ID; + } + + @Override + public Component getTitle() { + return Component.translatable("tile.integrationTableBlock.name"); + } + + @Override + public Renderer getIcon() { + return ICON; + } + + @Override + public int getDisplayHeight() { + return 72 + 2 + ReiUtils.PADDING * 2; + } + + @Override + public int getDisplayWidth(DisplayIntegration display) { + return 153 + 2 + ReiUtils.PADDING * 2; + } + + @Override + public List setupDisplay(DisplayIntegration display, Rectangle bounds) { + List ret = Lists.newArrayList(); + + ret.add(Widgets.createRecipeBase(bounds)); + + Point lu = new Point(bounds.getX() + ReiUtils.PADDING, bounds.getY() + ReiUtils.PADDING); + + // background + ret.add(Widgets.createTexturedWidget(BACKGROUND, lu.getX(), lu.getY(), 17, 21, 153, 72)); + + // animation + ret.add(Widgets.createDrawableWidget((guiGraphics, mouseX, mouseY, delta) -> + ReiUtils.drawAnimation( + guiGraphics, lu, BACKGROUND, + 720, + 147, 1, + 176, 0, + 4, 70, + ReiUtils.StartPosition.BOTTOM + ) + )); + + // text + ret.add(Widgets.createDrawableWidget((guiGraphics, mouseX, mouseY, delta) -> + { + PoseStack poseStack = guiGraphics.pose(); + poseStack.pushPose(); + poseStack.translate(lu.getX(), lu.getY(), 0); + Font font = Minecraft.getInstance().font; + long mj = display.requiredMicroJoules; + guiGraphics.drawString(font, MjAPI.formatMj(mj) + " MJ", 71, 52, Color.gray.getRGB(), false); + poseStack.popPose(); + })); + + // slot content + List inputs = display.getInputEntries(); + EntryIngredient center = inputs.get(0); + List surroundings = inputs.subList(1, inputs.size()); + int surroundingsIndexCounter = 0; + for (int y = 0; y < 3; ++y) { + for (int x = 0; x < 3; ++x) { + if (x == 1 && y == 1) { + ret.add(Widgets.createSlot(new Point(lu.getX() + 2 + x * 25, lu.getY() + 3 + y * 25)).markInput().entries(center).disableBackground()); + } else if (surroundingsIndexCounter < surroundings.size()) { + ret.add(Widgets.createSlot(new Point(lu.getX() + 2 + x * 25, lu.getY() + 3 + y * 25)).markInput().entries(surroundings.get(surroundingsIndexCounter)).disableBackground()); + surroundingsIndexCounter++; + } + } + } + + ret.add(Widgets.createSlot(new Point(lu.getX() + 121, lu.getY() + 28)).markOutput().entries(display.getOutputEntries().get(0)).disableBackground()); + return ret; + } } diff --git a/common/buildcraft/compat/module/rei/silicon/CategoryProgrammingTable.java b/common/buildcraft/compat/module/rei/silicon/CategoryProgrammingTable.java new file mode 100644 index 0000000..b5c51b8 --- /dev/null +++ b/common/buildcraft/compat/module/rei/silicon/CategoryProgrammingTable.java @@ -0,0 +1,109 @@ +package buildcraft.compat.module.rei.silicon; + +import buildcraft.api.BCModules; +import buildcraft.api.mj.MjAPI; +import buildcraft.compat.module.rei.ReiUtils; +import buildcraft.silicon.BCSiliconBlocks; +import com.google.common.collect.Lists; +import com.mojang.blaze3d.vertex.PoseStack; +import me.shedaniel.math.Point; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.gui.Renderer; +import me.shedaniel.rei.api.client.gui.widgets.Widget; +import me.shedaniel.rei.api.client.gui.widgets.Widgets; +import me.shedaniel.rei.api.client.registry.display.DisplayCategory; +import me.shedaniel.rei.api.common.category.CategoryIdentifier; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.util.EntryStacks; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; + +import java.awt.*; +import java.util.List; + +public enum CategoryProgrammingTable implements DisplayCategory { + INSTANCE; + + public static final CategoryIdentifier ID = CategoryIdentifier.of(new ResourceLocation(BCModules.SILICON.getModId(), "category_programming")); + public static final EntryStack ICON = EntryStacks.of(new ItemStack(BCSiliconBlocks.programmingTable.get())); + public static final ResourceLocation BACKGROUND = new ResourceLocation(BCModules.SILICON.getModId(), "textures/gui/programming_table.png"); + + @Override + public CategoryIdentifier getCategoryIdentifier() { + return ID; + } + + @Override + public Component getTitle() { + return Component.translatable("tile.programmingTableBlock.name"); + } + + @Override + public Renderer getIcon() { + return ICON; + } + + @Override + public int getDisplayHeight() { + return 72 + 2 + ReiUtils.PADDING * 2; + } + + @Override + public int getDisplayWidth(DisplayProgramming display) { + return 72 + 2 + ReiUtils.PADDING * 2; + } + + @Override + public List setupDisplay(DisplayProgramming display, Rectangle bounds) { + List ret = Lists.newArrayList(); + + ret.add(Widgets.createRecipeBase(bounds)); + + Point lu = new Point(bounds.getX() + ReiUtils.PADDING, bounds.getY() + ReiUtils.PADDING); + + // input slot + ret.add(Widgets.createTexturedWidget(BACKGROUND, lu.getX() + 2, lu.getY() + 27, 7, 35, 18, 18)); + + // arrow + ret.add(Widgets.createTexturedWidget(BACKGROUND, lu.getX() + 2 + 18 + 5, lu.getY() + 27 + 5, 28, 40, 11, 8)); + + // output slot + ret.add(Widgets.createTexturedWidget(BACKGROUND, lu.getX() + 2 + 18 + 5 + 11 + 5, lu.getY() + 27, 7, 89, 18, 18)); + + // animation background + ret.add(Widgets.createTexturedWidget(BACKGROUND, lu.getX() + 66, lu.getY() + 0, 163, 35, 6, 72)); + + // animation + ret.add(Widgets.createDrawableWidget((guiGraphics, mouseX, mouseY, delta) -> + ReiUtils.drawAnimation( + guiGraphics, lu, BACKGROUND, + (int) Math.max(10L, display.requiredMicroJoules / MjAPI.MJ / 50L), + 67, 1, + 176, 18, + 4, 70, + ReiUtils.StartPosition.BOTTOM + ) + )); + + // text + ret.add(Widgets.createDrawableWidget((guiGraphics, mouseX, mouseY, delta) -> + { + PoseStack poseStack = guiGraphics.pose(); + poseStack.pushPose(); + poseStack.translate(lu.getX(), lu.getY(), 0); + Font font = Minecraft.getInstance().font; + long mj = display.requiredMicroJoules; + guiGraphics.drawString(font, MjAPI.formatMj(mj) + " MJ", 10, 30 + 5 + 8 + 10, Color.gray.getRGB(), false); + poseStack.popPose(); + })); + + // slot content + ret.add(Widgets.createSlot(new Point(lu.getX() + 2 + 1, lu.getY() + 27 + 1)).markInput().entries(display.getInputEntries().get(0)).disableBackground()); + ret.add(Widgets.createSlot(new Point(lu.getX() + 2 + 18 + 5 + 11 + 5 + 1, lu.getY() + 27 + 1)).markOutput().entries(display.getOutputEntries().get(0)).disableBackground()); + + return ret; + } +} diff --git a/common/buildcraft/compat/module/rei/silicon/DisplayIntegration.java b/common/buildcraft/compat/module/rei/silicon/DisplayIntegration.java index 0330e39..834939d 100644 --- a/common/buildcraft/compat/module/rei/silicon/DisplayIntegration.java +++ b/common/buildcraft/compat/module/rei/silicon/DisplayIntegration.java @@ -1,29 +1,37 @@ package buildcraft.compat.module.rei.silicon; -import buildcraft.api.recipes.IIntegrationRecipeProvider; +import buildcraft.api.recipes.IntegrationRecipe; import me.shedaniel.rei.api.common.category.CategoryIdentifier; import me.shedaniel.rei.api.common.display.Display; import me.shedaniel.rei.api.common.entry.EntryIngredient; +import me.shedaniel.rei.api.common.util.EntryIngredients; import java.util.List; +import java.util.stream.Stream; public class DisplayIntegration implements Display { + private final List in; + private final EntryIngredient out; + public final long requiredMicroJoules; - public DisplayIntegration(IIntegrationRecipeProvider recipe) { + public DisplayIntegration(IntegrationRecipe recipe) { + in = EntryIngredients.ofIngredients(Stream.concat(List.of(recipe.getCenterStack()).stream(), recipe.getRequirements().stream()).map(ingredientStack -> ingredientStack.ingredient).toList()); + out = EntryIngredients.of(recipe.getExampleOutput()); + requiredMicroJoules = recipe.getRequiredMicroJoules(); } @Override public List getInputEntries() { - return List.of(); + return in; } @Override public List getOutputEntries() { - return List.of(); + return List.of(out); } @Override public CategoryIdentifier getCategoryIdentifier() { - throw new RuntimeException(); + return CategoryIntegrationTable.ID; } } diff --git a/common/buildcraft/compat/module/rei/silicon/DisplayProgramming.java b/common/buildcraft/compat/module/rei/silicon/DisplayProgramming.java new file mode 100644 index 0000000..df2cc30 --- /dev/null +++ b/common/buildcraft/compat/module/rei/silicon/DisplayProgramming.java @@ -0,0 +1,36 @@ +package buildcraft.compat.module.rei.silicon; + +import buildcraft.api.recipes.IProgrammingRecipe; +import me.shedaniel.rei.api.common.category.CategoryIdentifier; +import me.shedaniel.rei.api.common.display.Display; +import me.shedaniel.rei.api.common.entry.EntryIngredient; +import me.shedaniel.rei.api.common.util.EntryIngredients; + +import java.util.List; + +public class DisplayProgramming implements Display { + private final List in; + private final EntryIngredient out; + public final long requiredMicroJoules; + + public DisplayProgramming(IProgrammingRecipe recipe) { + in = EntryIngredients.ofIngredients(List.of(recipe.getInput().ingredient)); + out = EntryIngredients.of(recipe.getOutput()); + requiredMicroJoules = recipe.getEnergyCost(); + } + + @Override + public List getInputEntries() { + return in; + } + + @Override + public List getOutputEntries() { + return List.of(out); + } + + @Override + public CategoryIdentifier getCategoryIdentifier() { + return CategoryProgrammingTable.ID; + } +} diff --git a/common/buildcraft/compat/module/theoneprobe/BCPluginTOP.java b/common/buildcraft/compat/module/theoneprobe/BCPluginTOP.java index c9f414d..0f3ed7e 100644 --- a/common/buildcraft/compat/module/theoneprobe/BCPluginTOP.java +++ b/common/buildcraft/compat/module/theoneprobe/BCPluginTOP.java @@ -31,6 +31,7 @@ public enum BCPluginTOP implements Function, IBlockDisplayOv INSTANCE; static final String TOP_MOD_ID = "theoneprobe"; + @Override // @Method(modid = "theoneprobe") public Void apply(ITheOneProbe top) { top.registerBlockDisplayOverride(this); @@ -38,12 +39,14 @@ public Void apply(ITheOneProbe top) { return null; } + @Override // @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, Player player, Level world, BlockState blockState, IProbeHitData data) { return false; } + @Override // @Method(modid = "theoneprobe") // public String getID() public ResourceLocation getID() { @@ -51,6 +54,7 @@ public ResourceLocation getID() { return new ResourceLocation("buildcraftcompat.top"); } + @Override // @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, Player player, Level world, BlockState blockState, IProbeHitData data) { @@ -69,7 +73,6 @@ public void addProbeInfo(ProbeMode mode, IProbeInfo probeInfo, Player player, Le this.addAssemblyInfo(probeInfo, (IAssemblyCraft) entity); } } - } // @Method(modid = "theoneprobe") @@ -89,7 +92,6 @@ private void addAutoCraftInfo(IProbeInfo probeInfo, IAutoCraft crafter) { IProbeInfo mainInfo = probeInfo.vertical(); mainInfo.horizontal(mainInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER)).text(Component.translatable("buildcraft.waila.no_recipe")); } - } // @Method(modid = "theoneprobe") diff --git a/common/buildcraft/compat/module/waila/BaseWailaDataProvider.java b/common/buildcraft/compat/module/waila/BaseWailaDataProvider.java index 019d38c..f6c5170 100644 --- a/common/buildcraft/compat/module/waila/BaseWailaDataProvider.java +++ b/common/buildcraft/compat/module/waila/BaseWailaDataProvider.java @@ -2,12 +2,9 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.Entity; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; -import snownee.jade.api.BlockAccessor; -import snownee.jade.api.IBlockComponentProvider; -import snownee.jade.api.IServerDataProvider; -import snownee.jade.api.ITooltip; +import snownee.jade.api.*; import snownee.jade.api.config.IPluginConfig; //class BaseWailaDataProvider implements IWailaDataProvider @@ -22,7 +19,7 @@ public void appendTooltip(ITooltip iTooltip, BlockAccessor blockAccessor, IPlugi abstract void getWailaBody(ITooltip iTooltip, BlockAccessor accessor, IPluginConfig iPluginConfig); } -// static abstract class NBTProvider implements IServerDataProvider + // static abstract class NBTProvider implements IServerDataProvider static abstract class NBTProvider implements IServerDataProvider { @Override // public void appendServerData(CompoundTag tag, ServerPlayer player, Level blockAccessor, BlockEntity blockEntity, boolean showDetails) @@ -30,7 +27,25 @@ public void appendServerData(CompoundTag tag, BlockAccessor accessor) { getNBTData(tag, accessor); } -// abstract void getNBTData(CompoundTag tag, ServerPlayer player, Level blockAccessor, BlockEntity blockEntity, boolean showDetails); + // abstract void getNBTData(CompoundTag tag, ServerPlayer player, Level blockAccessor, BlockEntity blockEntity, boolean showDetails); abstract void getNBTData(CompoundTag tag, BlockAccessor accessor); } + + static abstract class BodyProviderEntity implements IEntityComponentProvider { + @Override + public void appendTooltip(ITooltip iTooltip, EntityAccessor blockAccessor, IPluginConfig iPluginConfig) { + getWailaBody(iTooltip, blockAccessor, iPluginConfig); + } + + abstract void getWailaBody(ITooltip iTooltip, EntityAccessor accessor, IPluginConfig iPluginConfig); + } + + static abstract class NBTProviderEntity implements IServerDataProvider { + @Override + public void appendServerData(CompoundTag tag, EntityAccessor entityAccessor) { + getNBTData(tag, (ServerPlayer) entityAccessor.getPlayer(), entityAccessor.getLevel(), entityAccessor.getEntity(), entityAccessor.showDetails()); + } + + abstract void getNBTData(CompoundTag tag, ServerPlayer player, Level world, Entity entity, boolean showDetails); + } } diff --git a/common/buildcraft/compat/module/waila/HWYLAPlugin.java b/common/buildcraft/compat/module/waila/HWYLAPlugin.java index 4410b1c..e8bbd4c 100644 --- a/common/buildcraft/compat/module/waila/HWYLAPlugin.java +++ b/common/buildcraft/compat/module/waila/HWYLAPlugin.java @@ -1,5 +1,6 @@ package buildcraft.compat.module.waila; +import buildcraft.api.robots.EntityRobotBase; import buildcraft.lib.block.BlockBCTile_Neptune; import buildcraft.lib.tile.TileBC_Neptune; import snownee.jade.api.*; @@ -14,11 +15,13 @@ public void register(IWailaCommonRegistration registrar) { IServerDataProvider laserTargetNbtProvider = new LaserTargetDataProvider.NBTProvider(); IServerDataProvider assemblyCraftNbtProvider = new AssemblyCraftDataProvider.NBTProvider(); IServerDataProvider mjStorageNbtProvider = new MjStorageDataProvider.NBTProvider(); + IServerDataProvider robotPowerNbtProvider = new RobotPowerDataProvider.NBTProvider(); registrar.registerBlockDataProvider(autoCraftNbtProvider, TileBC_Neptune.class); registrar.registerBlockDataProvider(laserTargetNbtProvider, TileBC_Neptune.class); registrar.registerBlockDataProvider(assemblyCraftNbtProvider, TileBC_Neptune.class); registrar.registerBlockDataProvider(mjStorageNbtProvider, TileBC_Neptune.class); + registrar.registerEntityDataProvider(robotPowerNbtProvider, EntityRobotBase.class); } @Override @@ -30,6 +33,7 @@ public void registerClient(IWailaClientRegistration registrar) { IBlockComponentProvider laserTargetBodyProvider = new LaserTargetDataProvider.BodyProvider(); IBlockComponentProvider assemblyCraftBodyProvider = new AssemblyCraftDataProvider.BodyProvider(); IBlockComponentProvider mjStorageBodyProvider = new MjStorageDataProvider.BodyProvider(); + IEntityComponentProvider robotPowerNbtProvider = new RobotPowerDataProvider.BodyProvider(); // registrar.registerComponentProvider(autoCraftBodyProvider, TooltipPosition.BODY, BlockBCTile_Neptune.class); // registrar.registerComponentProvider(laserTargetBodyProvider, TooltipPosition.BODY, BlockBCTile_Neptune.class); @@ -38,5 +42,6 @@ public void registerClient(IWailaClientRegistration registrar) { registrar.registerBlockComponent(laserTargetBodyProvider, BlockBCTile_Neptune.class); registrar.registerBlockComponent(assemblyCraftBodyProvider, BlockBCTile_Neptune.class); registrar.registerBlockComponent(mjStorageBodyProvider, BlockBCTile_Neptune.class); + registrar.registerEntityComponent(robotPowerNbtProvider, EntityRobotBase.class); } } diff --git a/common/buildcraft/compat/module/waila/RobotPowerDataProvider.java b/common/buildcraft/compat/module/waila/RobotPowerDataProvider.java new file mode 100644 index 0000000..4caf82b --- /dev/null +++ b/common/buildcraft/compat/module/waila/RobotPowerDataProvider.java @@ -0,0 +1,63 @@ +package buildcraft.compat.module.waila; + +import buildcraft.api.mj.MjAPI; +import buildcraft.api.robots.EntityRobotBase; +import buildcraft.robotics.BCRobotics; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.level.Level; +import snownee.jade.api.EntityAccessor; +import snownee.jade.api.ITooltip; +import snownee.jade.api.config.IPluginConfig; +import snownee.jade.api.ui.BoxStyle; +import snownee.jade.api.ui.IProgressStyle; +import snownee.jade.impl.ui.ProgressElement; +import snownee.jade.impl.ui.ProgressStyle; + +public class RobotPowerDataProvider { + static class BodyProvider extends BaseWailaDataProvider.BodyProviderEntity { + private static final IProgressStyle PROGRESS_STYLE = new ProgressStyle() + .color(-15731468, -16721961) + .textColor(DyeColor.WHITE.getTextColor()); + + @Override + public void getWailaBody(ITooltip currentTip, EntityAccessor accessor, IPluginConfig iPluginConfig) { + if (accessor.getEntity() instanceof EntityRobotBase) { + CompoundTag nbt = accessor.getServerData(); + if (nbt.contains("mj_storage", Tag.TAG_COMPOUND)) { + CompoundTag mj_storage_Tag = nbt.getCompound("mj_storage"); + long mj_capability = mj_storage_Tag.getLong("mj_capability"); + long mj_stored = mj_storage_Tag.getLong("mj_stored"); + currentTip.add(new ProgressElement((float) (((double) mj_stored) / ((double) mj_capability)), Component.literal(mj_stored + " MJ/" + mj_capability + "MJ"), PROGRESS_STYLE, BoxStyle.DEFAULT, false)); + } + } + } + + @Override + public ResourceLocation getUid() { + return ResourceLocation.tryBuild(BCRobotics.MODID, "robot_power_client_data"); + } + } + + static class NBTProvider extends BaseWailaDataProvider.NBTProviderEntity { + @Override + public void getNBTData(CompoundTag nbt, ServerPlayer player, Level world, Entity entity, boolean showDetails) { + if (entity instanceof EntityRobotBase) { + CompoundTag mj_storage_Tag = new CompoundTag(); + mj_storage_Tag.putLong("mj_capability", ((EntityRobotBase) entity).getBattery().getCapacity() / MjAPI.MJ); + mj_storage_Tag.putLong("mj_stored", ((EntityRobotBase) entity).getBattery().getStored() / MjAPI.MJ); + nbt.put("mj_storage", mj_storage_Tag); + } + } + + @Override + public ResourceLocation getUid() { + return ResourceLocation.tryBuild(BCRobotics.MODID, "robot_power_server_data"); + } + } +} diff --git a/resources/assets/buildcraftcompat/lang/en_us.json b/resources/assets/buildcraftcompat/lang/en_us.json index 627dd9c..3643699 100644 --- a/resources/assets/buildcraftcompat/lang/en_us.json +++ b/resources/assets/buildcraftcompat/lang/en_us.json @@ -57,9 +57,8 @@ "config.jade.plugin_buildcraftsilicon.assembly_server_data": "Assembly", "config.jade.plugin_buildcraftcore.mj_storage_client_data": "MJ Storage", "config.jade.plugin_buildcraftcore.mj_storage_server_data": "MJ Storage", - - // Calen FE compat - "tile.engineFe.name": "FE Engine", + "config.jade.plugin_buildcraftrobotics.robot_power_client_data": "Robot Power", + "config.jade.plugin_buildcraftrobotics.robot_power_server_data": "Robot Power", "null": "=w=" } diff --git a/resources/assets/buildcraftcompat/lang/zh_cn.json b/resources/assets/buildcraftcompat/lang/zh_cn.json index 3ca27f3..9482639 100644 --- a/resources/assets/buildcraftcompat/lang/zh_cn.json +++ b/resources/assets/buildcraftcompat/lang/zh_cn.json @@ -52,9 +52,8 @@ "config.jade.plugin_buildcraftsilicon.assembly_server_data": "装配台", "config.jade.plugin_buildcraftcore.mj_storage_client_data": "MJ存储", "config.jade.plugin_buildcraftcore.mj_storage_server_data": "MJ存储", - - // Calen FE compat - "tile.engineFe.name": "FE引擎", + "config.jade.plugin_buildcraftrobotics.robot_power_client_data": "机器人能量", + "config.jade.plugin_buildcraftrobotics.robot_power_server_data": "机器人能量", "null": "=w=" } diff --git a/resources/assets/buildcraftcompat/models/tile/engine_fe.jsonbc b/resources/assets/buildcraftcompat/models/tile/engine_fe.jsonbc deleted file mode 100644 index 0b16eaa..0000000 --- a/resources/assets/buildcraftcompat/models/tile/engine_fe.jsonbc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "textures": { - "#back":"buildcraftcompat:block/engine/fe/back", - "#side":"buildcraftcompat:block/engine/fe/side" - }, - "parent":"buildcraftlib:models/tile/engine_base" -} \ No newline at end of file diff --git a/resources/assets/buildcraftcompat/textures/block/engine/fe/back.png b/resources/assets/buildcraftcompat/textures/block/engine/fe/back.png deleted file mode 100644 index 06da85225017205de7397d88ff759b3a94821106..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 460 zcmV;-0WEj-sCeeS$ouV}3m=N$L@eH4Wd zMzenIU=iW@d;(Bw#R5#zM2wO1`ON>s;cyt=R#gchFijHx`~4nO9U9bHQPlysTrNu; zI)f0x5GJLx0M}YqMFu_^%o&IXA%q2Z&Y;(%l)emJuh(DzkWxZb$vOW8257C}y+=eo z4K|z2;-_;C0OuSzXMmCCm$cTt4A!ELxaS@@=W$j5@BJ{x96Z;czxkJ$cDt_Gw1Y(i z@BNrYHyMEa_4)6d*P`2d7zyC|62=&E&STMfvlt_#ln;YB?Y_EQlYg!8JpKS;V&J`$ec0y!0000 zi-E7Opkwyi1E)7Vco(uaukUdO(+=ykrg!F+#&&YJv~(yKcXBYC$uVb6QJXfC=P<*D z>vvtkukst;E6-oEs`|y!pXPN6{lC}#U^vzOgT2Q2fbgF)xk1+p{#*mPkipZ{&t;uc GLK6U9sb}v1 From c7dadcfc71c1f75565a4d0ef85dbdd4ce5d0a81d Mon Sep 17 00:00:00 2001 From: CalenXwX Date: Thu, 24 Apr 2025 20:12:01 +0800 Subject: [PATCH 9/9] Update gitsubmodule --- BuildCraft | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BuildCraft b/BuildCraft index 5b2a59e..6ef7425 160000 --- a/BuildCraft +++ b/BuildCraft @@ -1 +1 @@ -Subproject commit 5b2a59ec97573ef743365a4b1e86eee4fa8f62c8 +Subproject commit 6ef7425b1d2003f353058d5ec057884440e4ca83